diff --git a/example_projects/gowin_fmax_test_prj_template_v1/.gitignore b/example_projects/gowin_fmax_test_prj_template_v1/.gitignore new file mode 100755 index 0000000..f477cea --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/.gitignore @@ -0,0 +1,21 @@ +#------------------------------------------------------------------------------ +# .gitignore for Gowin IDE +# Konstantin Pavlov, pavlovconst@gmail.com +#------------------------------------------------------------------------------ + +# INFO ------------------------------------------------------------------------ +# rename the file to ".gitignore" and place into your Gowin project directory +# + + +# junk files +*.gprj.user +impl/gwsynthesis/*.html +impl/gwsynthesis/*.xml +impl/gwsynthesis/*.log +impl/gwsynthesis/*.vg + +# junk directories +/impl/pnr +/impl/temp + diff --git a/example_projects/gowin_fmax_test_prj_template_v1/clean_gowin.bat b/example_projects/gowin_fmax_test_prj_template_v1/clean_gowin.bat new file mode 100755 index 0000000..10eda8b --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/clean_gowin.bat @@ -0,0 +1,28 @@ +@echo off +rem ------------------------------------------------------------------------------ +rem clean_gowin.bat +rem published as part of https://github.com/pConst/basic_verilog +rem Konstantin Pavlov, pavlovconst@gmail.com +rem ------------------------------------------------------------------------------ + +rem Use this file as a boilerplate for your custom clean script +rem for Gowin IDE projects + + +rem preserving .\impl\gwsynthesis\test.prj file +del /s /f /q .\impl\gwsynthesis\*.html +del /s /f /q .\impl\gwsynthesis\*.xml +del /s /f /q .\impl\gwsynthesis\*.log +del /s /f /q .\impl\gwsynthesis\*.vg + +del /s /f /q .\impl\pnr\* +rmdir /s /q .\impl\pnr\ + +del /s /f /q .\impl\temp\* +rmdir /s /q .\impl\temp\ + +del /s /f /q .*.gprj.user + +pause +goto :eof + diff --git a/example_projects/gowin_fmax_test_prj_template_v1/impl/gwsynthesis/test.prj b/example_projects/gowin_fmax_test_prj_template_v1/impl/gwsynthesis/test.prj new file mode 100755 index 0000000..31e62ff --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/impl/gwsynthesis/test.prj @@ -0,0 +1,23 @@ + + + + beta + + + + + + + + + + + diff --git a/example_projects/gowin_fmax_test_prj_template_v1/impl/project_process_config.json b/example_projects/gowin_fmax_test_prj_template_v1/impl/project_process_config.json new file mode 100755 index 0000000..5c7e9f1 --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/impl/project_process_config.json @@ -0,0 +1,80 @@ +{ + "Allow_Duplicate_Modules" : false, + "Annotated_Properties_for_Analyst" : true, + "BACKGROUND_PROGRAMMING" : "off", + "COMPRESS" : false, + "CRC_CHECK" : true, + "Clock_Conversion" : true, + "DONE" : false, + "DOWNLOAD_SPEED" : "default", + "Default_Enum_Encoding" : "default", + "Disable_Insert_Pad" : false, + "ENCRYPTION_KEY" : false, + "ENCRYPTION_KEY_TEXT" : "00000000000000000000000000000000", + "FORMAT" : "binary", + "FSM Compiler" : true, + "Fanout_Guide" : 10000, + "Frequency" : "Auto", + "Generate_Constraint_File_of_Ports" : false, + "Generate_IBIS_File" : false, + "Generate_Plain_Text_Timing_Report" : false, + "Generate_Post_PNR_Simulation_Model_File" : false, + "Generate_Post_Place_File" : false, + "Generate_SDF_File" : false, + "GwSyn_Loop_Limit" : 2000, + "HOTBOOT" : false, + "I2C" : false, + "I2C_SLAVE_ADDR" : "00", + "Implicit_Initial_Value_Support" : false, + "IncludePath" : [ + + ], + "Incremental_Compile" : "", + "Initialize_Primitives" : false, + "JTAG" : false, + "MODE_IO" : false, + "MSPI" : false, + "Multiple_File_Compilation_Unit" : true, + "Number_of_Critical_Paths" : "", + "Number_of_Start/End_Points" : "", + "OUTPUT_BASE_NAME" : "test", + "POWER_ON_RESET" : false, + "PRINT_BSRAM_VALUE" : true, + "PROGRAM_DONE_BYPASS" : false, + "Pipelining" : true, + "PlaceInRegToIob" : true, + "PlaceIoRegToIob" : true, + "PlaceOutRegToIob" : true, + "Place_Option" : "0", + "Process_Configuration_Verion" : "1.0", + "Promote_Physical_Constraint_Warning_to_Error" : true, + "Push_Tristates" : true, + "READY" : false, + "RECONFIG_N" : false, + "Ram_RW_Check" : true, + "Report_Auto-Placed_Io_Information" : false, + "Resolve_Mixed_Drivers" : false, + "Resource_Sharing" : true, + "Retiming" : false, + "Route_Option" : "0", + "Run_Timing_Driven" : true, + "SECURE_MODE" : false, + "SECURITY_BIT" : true, + "SPI_FLASH_ADDR" : "00000000", + "SSPI" : false, + "Show_All_Warnings" : false, + "Synthesis On/Off Implemented as Translate On/Off" : false, + "Synthesize_tool" : "GowinSyn", + "TopModule" : "", + "USERCODE" : "default", + "Unused_Pin" : "As_input_tri_stated_with_pull_up", + "Update_Compile_Point_Timing_Data" : false, + "Use_Clock_Period_for_Unconstrainted IO" : false, + "Use_SCF" : false, + "VHDL_Standard" : "VHDL_Std_1993", + "Verilog_Standard" : "Vlg_Std_Sysv2017", + "WAKE_UP" : "0", + "Write_Vendor_Constraint_File" : true, + "dsp_balance" : false, + "show_all_warnings" : false +} \ No newline at end of file diff --git a/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.ipc b/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.ipc new file mode 100755 index 0000000..72406bb --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.ipc @@ -0,0 +1,24 @@ +[General] +ipc_version=4 +file=sys_pll +module=sys_pll +target_device=gw1nr9c-004 +type=clock_rpll +version=1.0 + +[Config] +CKLOUTD3=false +CLKFB_SOURCE=0 +CLKIN_FREQ=27 +CLKOUTD=false +CLKOUTP=false +CLKOUT_BYPASS=false +CLKOUT_DIVIDE_DYN=true +CLKOUT_FREQ=250 +CLKOUT_TOLERANCE=3 +DYNAMIC=false +LANG=0 +LOCK_EN=true +MODE_GENERAL=true +PLL_PWD=false +RESET_PLL=false diff --git a/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.mod b/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.mod new file mode 100755 index 0000000..639fbe4 --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.mod @@ -0,0 +1,31 @@ +-series GW1NR +-device GW1NR-9C +-package QFN88P +-part_number GW1NR-LV9QN88PC6/I5 + + +-mod_name sys_pll +-file_name sys_pll +-path J:/fpga_tests/fifo_single_clock_reg_v2_test_gw/ip/sys_pll/ +-type PLL +-rPll true +-file_type vlg +-dev_type GW1NR-9C +-dyn_idiv_sel false +-idiv_sel 4 +-dyn_fbdiv_sel false +-fbdiv_sel 37 +-dyn_odiv_sel false +-odiv_sel 2 +-dyn_da_en false +-rst_sig false +-rst_sig_p false +-fclkin 27 +-clkfb_sel 0 +-en_lock true +-clkout_bypass false +-en_clkoutp false +-clkoutp_bypass false +-en_clkoutd false +-clkoutd_bypass false +-en_clkoutd3 false \ No newline at end of file diff --git a/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.v b/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.v new file mode 100755 index 0000000..351fef6 --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll.v @@ -0,0 +1,63 @@ +//Copyright (C)2014-2022 Gowin Semiconductor Corporation. +//All rights reserved. +//File Title: IP file +//GOWIN Version: V1.9.8.05 +//Part Number: GW1NR-LV9QN88PC6/I5 +//Device: GW1NR-9C +//Created Time: Sun May 15 09:43:06 2022 + +module sys_pll (clkout, lock, clkin); + +output clkout; +output lock; +input clkin; + +wire clkoutp_o; +wire clkoutd_o; +wire clkoutd3_o; +wire gw_gnd; + +assign gw_gnd = 1'b0; + +rPLL rpll_inst ( + .CLKOUT(clkout), + .LOCK(lock), + .CLKOUTP(clkoutp_o), + .CLKOUTD(clkoutd_o), + .CLKOUTD3(clkoutd3_o), + .RESET(gw_gnd), + .RESET_P(gw_gnd), + .CLKIN(clkin), + .CLKFB(gw_gnd), + .FBDSEL({gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd}), + .IDSEL({gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd}), + .ODSEL({gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd,gw_gnd}), + .PSDA({gw_gnd,gw_gnd,gw_gnd,gw_gnd}), + .DUTYDA({gw_gnd,gw_gnd,gw_gnd,gw_gnd}), + .FDLY({gw_gnd,gw_gnd,gw_gnd,gw_gnd}) +); + +defparam rpll_inst.FCLKIN = "27"; +defparam rpll_inst.DYN_IDIV_SEL = "false"; +defparam rpll_inst.IDIV_SEL = 3; +defparam rpll_inst.DYN_FBDIV_SEL = "false"; +defparam rpll_inst.FBDIV_SEL = 36; +defparam rpll_inst.DYN_ODIV_SEL = "false"; +defparam rpll_inst.ODIV_SEL = 2; +defparam rpll_inst.PSDA_SEL = "0000"; +defparam rpll_inst.DYN_DA_EN = "false"; +defparam rpll_inst.DUTYDA_SEL = "1000"; +defparam rpll_inst.CLKOUT_FT_DIR = 1'b1; +defparam rpll_inst.CLKOUTP_FT_DIR = 1'b1; +defparam rpll_inst.CLKOUT_DLY_STEP = 0; +defparam rpll_inst.CLKOUTP_DLY_STEP = 0; +defparam rpll_inst.CLKFB_SEL = "internal"; +defparam rpll_inst.CLKOUT_BYPASS = "false"; +defparam rpll_inst.CLKOUTP_BYPASS = "false"; +defparam rpll_inst.CLKOUTD_BYPASS = "false"; +defparam rpll_inst.DYN_SDIV_SEL = 2; +defparam rpll_inst.CLKOUTD_SRC = "CLKOUT"; +defparam rpll_inst.CLKOUTD3_SRC = "CLKOUT"; +defparam rpll_inst.DEVICE = "GW1NR-9C"; + +endmodule //sys_pll diff --git a/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll_tmp.v b/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll_tmp.v new file mode 100755 index 0000000..ca5c1d1 --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/ip/sys_pll/sys_pll_tmp.v @@ -0,0 +1,18 @@ +//Copyright (C)2014-2022 Gowin Semiconductor Corporation. +//All rights reserved. +//File Title: Template file for instantiation +//GOWIN Version: V1.9.8.05 +//Part Number: GW1NR-LV9QN88PC6/I5 +//Device: GW1NR-9C +//Created Time: Sun May 15 09:43:06 2022 + +//Change the instance name and port connections to the signal names +//--------Copy here to design-------- + + sys_pll your_instance_name( + .clkout(clkout_o), //output clkout + .lock(lock_o), //output lock + .clkin(clkin_i) //input clkin + ); + +//--------Copy end------------------- diff --git a/example_projects/gowin_fmax_test_prj_template_v1/src/clk_divider.sv b/example_projects/gowin_fmax_test_prj_template_v1/src/clk_divider.sv new file mode 100755 index 0000000..5e25735 --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/src/clk_divider.sv @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------ +// clk_divider.sv +// published as part of https://github.com/pConst/basic_verilog +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// Divides main clock to get derivative slower synchronous clocks +// + +/* --- INSTANTIATION TEMPLATE BEGIN --- + +clk_divider #( + .WIDTH( 32 ) +) CD1 ( + .clk( clk ), + .nrst( 1'b1 ), + .ena( 1'b1 ), + .out( ) +); + +--- INSTANTIATION TEMPLATE END ---*/ + + +module clk_divider #( parameter + WIDTH = 32 +)( + input clk, + input nrst, + input ena, + output logic [(WIDTH-1):0] out = '0 +); + + +always_ff @(posedge clk) begin + if ( ~nrst ) begin + out[(WIDTH-1):0] <= '0; + end else if (ena) begin + out[(WIDTH-1):0] <= out[(WIDTH-1):0] + 1'b1; + end +end + +endmodule diff --git a/example_projects/gowin_fmax_test_prj_template_v1/src/clogb2.svh b/example_projects/gowin_fmax_test_prj_template_v1/src/clogb2.svh new file mode 100755 index 0000000..5c7336e --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/src/clogb2.svh @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// clogb2.svh +// published as part of https://github.com/pConst/basic_verilog +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// Calculates counter/address width based on specified vector/RAM depth +// +// Function should be instantiated inside a module +// But you are free to call it from anywhere by its hierarchical name +// +// To add clogb2 function to your module: +// `include "clogb2.svh" +// + +function integer clogb2; + input integer depth; + + for( clogb2=0; depth>0; clogb2=clogb2+1 ) begin + depth = depth >> 1; + end +endfunction + diff --git a/example_projects/gowin_fmax_test_prj_template_v1/src/define.svh b/example_projects/gowin_fmax_test_prj_template_v1/src/define.svh new file mode 100755 index 0000000..4f63580 --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/src/define.svh @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// Gowin test project template +// published as part of https://github.com/pConst/basic_verilog +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + + +// Vivado bugfix =============================================================== + + // This is a workaround for Vivado bug of not providing errors + // when using undeclared signals in your code + // See https://forums.xilinx.com/t5/Synthesis/Bug-in-handling-undeclared-signals-in-instance-statement-named/td-p/300127 + //`define VIVADO_MODULE_HEADER `default_nettype none + //`define VIVADO_MODULE_FOOTER `default_nettype wire + + // Declare these stubs to safely reuse your Vivado modules in non-Xilinx FPGA projects + `define VIVADO_MODULE_HEADER + `define VIVADO_MODULE_FOOTER + +// ============================================================================= + + `define INC( AVAL ) \ + ``AVAL <= ``AVAL + 1'b1; + + `define DEC( AVAL ) \ + ``AVAL <= ``AVAL - 1'b1; + + `define SET( AVAL ) \ + ``AVAL <= 1'b1; + + `define RESET( AVAL ) \ + ``AVAL <= 1'b0; diff --git a/example_projects/gowin_fmax_test_prj_template_v1/src/delay.sv b/example_projects/gowin_fmax_test_prj_template_v1/src/delay.sv new file mode 100755 index 0000000..3d7b69f --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/src/delay.sv @@ -0,0 +1,211 @@ +//------------------------------------------------------------------------------ +// delay.sv +// published as part of https://github.com/pConst/basic_verilog +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------- +// Static Delay for arbitrary signal, v2 +// Another equivalent names for this module: +// conveyor.sv +// synchronizer.sv +// +// Tip for Xilinx-based implementations: Leave nrst=1'b1 and ena=1'b1 on +// purpose of inferring Xilinx`s SRL16E/SRL32E primitives +// +// CAUTION: delay module is widely used for synchronizing signals across clock +// domains. When synchronizing, please exclude input data paths from timing +// analysis manually by writing appropriate set_false_path SDC constraint +// +// Version 2 introduces "ALTERA_BLOCK_RAM" option to implement delays using +// block RAM. Quartus can make shifters on block RAM automatically +// using 'altshift_taps' internal module when "Auto Shift Register +// Replacement" option is ON +// + +/* --- INSTANTIATION TEMPLATE BEGIN --- + +delay #( + .LENGTH( 2 ), + .WIDTH( 1 ), + .TYPE( "CELLS" ), + .REGISTER_OUTPUTS( "FALSE" ) +) S1 ( + .clk( clk ), + .nrst( 1'b1 ), + .ena( 1'b1 ), + + .in( ), + .out( ) +); + +--- INSTANTIATION TEMPLATE END ---*/ + + +module delay #( parameter + LENGTH = 2, // delay/synchronizer chain length + WIDTH = 1, // signal width + + TYPE = "CELLS", // "ALTERA_BLOCK_RAM" infers block ram fifo + // "ALTERA_TAPS" infers altshift_taps + // all other values infer registers + + REGISTER_OUTPUTS = "FALSE", // for block RAM implementations: "TRUE" means that + // last delay stage will be implemented + // by means of cell registers to improve timing + // all other values infer block RAMs only + + CNTR_W = $clog2(LENGTH) +)( + input clk, + input nrst, + input ena, + + input [WIDTH-1:0] in, + output [WIDTH-1:0] out +); + +generate + + if ( LENGTH == 0 ) begin + + assign out[WIDTH-1:0] = in[WIDTH-1:0]; + + end else if( LENGTH == 1 ) begin + + logic [WIDTH-1:0] data = '0; + always_ff @(posedge clk) begin + if( ~nrst ) begin + data[WIDTH-1:0] <= '0; + end else if( ena ) begin + data[WIDTH-1:0] <= in[WIDTH-1:0]; + end + end + assign out[WIDTH-1:0] = data[WIDTH-1:0]; + + end else begin + if( TYPE=="ALTERA_BLOCK_RAM" && LENGTH>=3 ) begin + + logic [WIDTH-1:0] fifo_out; + logic full; + logic [CNTR_W-1:0] usedw; + + logic fifo_out_ena; + if( REGISTER_OUTPUTS=="TRUE" ) begin + assign fifo_out_ena = (usedw[CNTR_W-1:0] == LENGTH-1); + end else begin + assign fifo_out_ena = full; + end + + scfifo #( + .LPM_WIDTH( WIDTH ), + .LPM_NUMWORDS( LENGTH ), // must be at least 4 + .LPM_WIDTHU( CNTR_W ), + .LPM_SHOWAHEAD( "ON" ), + .UNDERFLOW_CHECKING( "ON" ), + .OVERFLOW_CHECKING( "ON" ), + .ENABLE_ECC( "FALSE" ), + .ALLOW_RWCYCLE_WHEN_FULL( "ON" ), + .USE_EAB( "ON" ) + ) internal_fifo ( + .clock( clk ), + .aclr( 1'b0 ), + .sclr( ~nrst ), + + .data( in[WIDTH-1:0] ), + .wrreq( ena ), + .rdreq( ena && fifo_out_ena ), + + .q( fifo_out[WIDTH-1:0] ), + .empty( ), + .full( full ), + .almost_full( ), + .almost_empty( ), + .usedw( usedw[CNTR_W-1:0] ), + .eccstatus( ) + ); + + logic [WIDTH-1:0] reg_out = '0; + always_ff @(posedge clk) begin + if( ~nrst ) begin + reg_out[WIDTH-1:0] <= '0; + end else if( ena && fifo_out_ena ) begin + reg_out[WIDTH-1:0] <= fifo_out[WIDTH-1:0]; + end + end + + if( REGISTER_OUTPUTS=="TRUE" ) begin + assign out[WIDTH-1:0] = reg_out[WIDTH-1:0]; + end else begin + // avoiding first word fall-through + assign out[WIDTH-1:0] = (fifo_out_ena)?(fifo_out[WIDTH-1:0]):('0); + end + + end else if( TYPE=="ALTERA_TAPS" && LENGTH>=2 ) begin + + logic [WIDTH-1:0] fifo_out; + logic [CNTR_W-1:0] delay_cntr = CNTR_W'(LENGTH-1); + + logic fifo_out_ena; + assign fifo_out_ena = (delay_cntr[CNTR_W-1:0] == '0); + + always_ff @(posedge clk) begin + if( ~nrst ) begin + delay_cntr[CNTR_W-1:0] <= CNTR_W'(LENGTH-1); + end else if( ena && ~fifo_out_ena ) begin + delay_cntr[CNTR_W-1:0] <= delay_cntr[CNTR_W-1:0] - 1'b1; + end + end + + altshift_taps #( + .intended_device_family( "Cyclone V" ), + .lpm_hint( "RAM_BLOCK_TYPE=AUTO" ), + .lpm_type( "altshift_taps" ), + .number_of_taps( 1 ), + .tap_distance( (REGISTER_OUTPUTS=="TRUE")?(LENGTH-1):(LENGTH) ), // min. of 3 + .width( WIDTH ) + ) internal_taps ( + //.aclr( 1'b0 ), + //.sclr( ~nrst ), + .clock( clk ), + .clken( ena ), + .shiftin( in[WIDTH-1:0] ), + .shiftout( fifo_out[WIDTH-1:0] ) + ); + + if( REGISTER_OUTPUTS=="TRUE" ) begin + logic [WIDTH-1:0] reg_out = '0; + always_ff @(posedge clk) begin + if( ~nrst ) begin + reg_out[WIDTH-1:0] <= '0; + end else if( ena && fifo_out_ena ) begin + reg_out[WIDTH-1:0] <= fifo_out[WIDTH-1:0]; + end + end + assign out[WIDTH-1:0] = reg_out[WIDTH-1:0]; + end else begin + assign out[WIDTH-1:0] = fifo_out[WIDTH-1:0]; + end + + end else begin + + logic [LENGTH:1][WIDTH-1:0] data = '0; + always_ff @(posedge clk) begin + integer i; + if( ~nrst ) begin + data <= '0; + end else if( ena ) begin + for(i=LENGTH-1; i>0; i--) begin + data[i+1][WIDTH-1:0] <= data[i][WIDTH-1:0]; + end + data[1][WIDTH-1:0] <= in[WIDTH-1:0]; + end + end + assign out[WIDTH-1:0] = data[LENGTH][WIDTH-1:0]; + + end // if TYPE + end // if LENGTH + +endgenerate + +endmodule diff --git a/example_projects/gowin_fmax_test_prj_template_v1/src/edge_detect.sv b/example_projects/gowin_fmax_test_prj_template_v1/src/edge_detect.sv new file mode 100755 index 0000000..8c3bed3 --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/src/edge_detect.sv @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// edge_detect.sv +// published as part of https://github.com/pConst/basic_verilog +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// Edge detector, ver.4 +// +// (new!) Added WIDTH parameter to simplify instantiating arrays of edge detectors +// (new!) Made reset to be asynchronous +// +// Added parameter to select combinational implementation (zero clocks delay) +// or registered implementation (one clocks delay) +// +// In case when "in" port has toggle rate 100% (changes every clock period) +// "rising" and "falling" outputs will completely replicate input +// "both" output will be always active in this case +// + + +/* --- INSTANTIATION TEMPLATE BEGIN --- + +edge_detect #( + .WIDTH( 32 ), + .REGISTER_OUTPUTS( 1'b1 ) +) in_ed ( + .clk( clk ), + .anrst( 1'b1 ), + .in( in[31:0] ), + .rising( in_rise[31:0] ), + .falling( ), + .both( ) +); + +--- INSTANTIATION TEMPLATE END ---*/ + + +module edge_detect #( parameter + bit [7:0] WIDTH = 1, // signal width + bit [0:0] REGISTER_OUTPUTS = 1'b0 // 0 - comb. implementation (default) + // 1 - registered implementation +)( + input clk, + input anrst, + + input [WIDTH-1:0] in, + output logic [WIDTH-1:0] rising, + output logic [WIDTH-1:0] falling, + output logic [WIDTH-1:0] both +); + +// data delay line +logic [WIDTH-1:0] in_d = '0; +always_ff @(posedge clk or negedge anrst) begin + if ( ~anrst ) begin + in_d[WIDTH-1:0] <= '0; + end else begin + in_d[WIDTH-1:0] <= in[WIDTH-1:0]; + end +end + +logic [WIDTH-1:0] rising_comb; +logic [WIDTH-1:0] falling_comb; +logic [WIDTH-1:0] both_comb; +always_comb begin + rising_comb[WIDTH-1:0] = {WIDTH{anrst}} & (in[WIDTH-1:0] & ~in_d[WIDTH-1:0]); + falling_comb[WIDTH-1:0] = {WIDTH{anrst}} & (~in[WIDTH-1:0] & in_d[WIDTH-1:0]); + both_comb[WIDTH-1:0] = {WIDTH{anrst}} & (rising_comb[WIDTH-1:0] | falling_comb[WIDTH-1:0]); +end + +generate + if( REGISTER_OUTPUTS==1'b0 ) begin + + // combinational outputs, no delay + always_comb begin + rising[WIDTH-1:0] = rising_comb[WIDTH-1:0]; + falling[WIDTH-1:0] = falling_comb[WIDTH-1:0]; + both[WIDTH-1:0] = both_comb[WIDTH-1:0]; + end // always + + end else begin + + // registered outputs, 1 cycle delay + always_ff @(posedge clk or negedge anrst) begin + if( ~anrst ) begin + rising[WIDTH-1:0] <= '0; + falling[WIDTH-1:0] <= '0; + both[WIDTH-1:0] <= '0; + end else begin + rising[WIDTH-1:0] <= rising_comb[WIDTH-1:0]; + falling[WIDTH-1:0] <= falling_comb[WIDTH-1:0]; + both[WIDTH-1:0] <= both_comb[WIDTH-1:0]; + end // always + end // if + + end // end else +endgenerate + +endmodule diff --git a/example_projects/gowin_fmax_test_prj_template_v1/src/main.sdc b/example_projects/gowin_fmax_test_prj_template_v1/src/main.sdc new file mode 100755 index 0000000..224ec9c --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/src/main.sdc @@ -0,0 +1,9 @@ +#------------------------------------------------------------------------------ +# Gowin test project template +# published as part of https://github.com/pConst/basic_verilog +# Konstantin Pavlov, pavlovconst@gmail.com +#------------------------------------------------------------------------------ + +# main reference clock, 27 MHz +create_clock -period 37.037-waveform { 0.000 18.518 } [get_ports {clk27}] + diff --git a/example_projects/gowin_fmax_test_prj_template_v1/src/main.sv b/example_projects/gowin_fmax_test_prj_template_v1/src/main.sv new file mode 100755 index 0000000..7fdf7d6 --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/src/main.sv @@ -0,0 +1,131 @@ +//------------------------------------------------------------------------------ +// Gowin test project template +// published as part of https://github.com/pConst/basic_verilog +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------ +// Gowin IDE test project template, v1 +// Compatible with Tang Nano 9K board +// +// - use this as a boilerplate project for fast prototyping +// - inputs and outputs are registered to allow valid timequest output +// even if your custom logic/IPs have combinational outputs +// - SDC constraint file assigns clk to 500MHz to force fitter to synthesize +// the fastest possible circuit +// + +`timescale 1ns / 1ps + +`include "define.svh" + + +`define WIDTH 16 + +module main( + input clk27, + + input [1:0] key, + output [5:0] led, + + input [`WIDTH-1:0] in_data, + output logic [`WIDTH-1:0] out_data +); + + +// clocks ====================================================================== + +logic sys_pll_locked; // asyn +logic clk250; + +logic nrst; + +sys_pll sys_pll_b ( + .clkin( clk27 ), + .clkout( clk250 ), + .lock( sys_pll_locked ) +); + +assign led[0] = sys_pll_locked; + +logic [31:0] div_clk250; +clk_divider #( + .WIDTH( 32 ) +) cd_500 ( + .clk( clk250 ), + .nrst( nrst ), + .ena( 1'b1 ), + .out( div_clk250[31:0] ) +); + +assign led[1] = div_clk250[27]; + +// nrst ======================================================================== +logic [1:0] key_s; + +always_ff @(posedge clk250) begin + nrst <= ~key_s[0]; // external reset +end + +assign led[2] = ~key_s[0]; +assign led[3] = ~key_s[1]; + +// buttons ===================================================================== + +delay #( + .LENGTH( 2 ), + .WIDTH( 2 ) +) sw_SYNC_ATTR ( + .clk( clk250 ), + .nrst( 1'b1 ), // dont use nrst here! + .ena( 1'b1 ), + .in( ~key[1:0] ), + .out( key_s[1:0] ) +); + +logic [1:0] key_s_rise; +logic [1:0] key_s_fall; + +edge_detect #( + .WIDTH( 2 ) +) sw_s_ed ( + .clk( clk250 ), + .anrst( 1'b1 ), + .in( key_s[1:0] ), + .rising( key_s_rise[1:0] ), + .falling( key_s_fall[1:0] ), + .both( ) +); + +// ============================================================================= + +// input registers +logic [`WIDTH-1:0] in_data_reg = 0; +always_ff @(posedge clk250) begin + if( ~nrst ) begin + in_data_reg[`WIDTH-1:0] <= '0; + end else begin + in_data_reg[`WIDTH-1:0] <= in_data[`WIDTH-1:0]; + end +end + +// place your test logic here ================================================== + +logic [`WIDTH-1:0] out_data_comb = 0; +always_comb begin + out_data_comb[`WIDTH-1:0] <= in_data_reg[`WIDTH-1:0] ^ div_clk250[31:0]; +end + +// output registers +always_ff @(posedge clk250) begin + if( ~nrst ) begin + out_data[`WIDTH-1:0] <= 0; + end else begin + out_data[`WIDTH-1:0] <= out_data_comb[`WIDTH-1:0]; + end +end + +`include "clogb2.svh" + +endmodule + diff --git a/example_projects/gowin_fmax_test_prj_template_v1/src/test.cst b/example_projects/gowin_fmax_test_prj_template_v1/src/test.cst new file mode 100755 index 0000000..4f4b21e --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/src/test.cst @@ -0,0 +1,26 @@ +#------------------------------------------------------------------------------ +# Gowin test project template +# published as part of https://github.com/pConst/basic_verilog +# Konstantin Pavlov, pavlovconst@gmail.com +#------------------------------------------------------------------------------ + +IO_LOC "led[5]" 16; +IO_PORT "led[5]" PULL_MODE=UP DRIVE=8; +IO_LOC "led[4]" 15; +IO_PORT "led[4]" PULL_MODE=UP DRIVE=8; +IO_LOC "led[3]" 14; +IO_PORT "led[3]" PULL_MODE=UP DRIVE=8; +IO_LOC "led[2]" 13; +IO_PORT "led[2]" PULL_MODE=UP DRIVE=8; +IO_LOC "led[1]" 11; +IO_PORT "led[1]" PULL_MODE=UP DRIVE=8; +IO_LOC "led[0]" 10; +IO_PORT "led[0]" PULL_MODE=UP DRIVE=8; + +IO_LOC "key[0]" 4; +IO_PORT "key[0]" PULL_MODE=UP; +IO_LOC "key[1]" 3; +IO_PORT "key[1]" PULL_MODE=UP; + +IO_LOC "clk27" 52; +IO_PORT "clk27" IO_TYPE=LVCMOS33 PULL_MODE=UP; diff --git a/example_projects/gowin_fmax_test_prj_template_v1/test.gprj b/example_projects/gowin_fmax_test_prj_template_v1/test.gprj new file mode 100755 index 0000000..880a8fa --- /dev/null +++ b/example_projects/gowin_fmax_test_prj_template_v1/test.gprj @@ -0,0 +1,18 @@ + + + + + 5 + gw1nr9c-004 + + + + + + + + + + + +