`timescale 1 ns / 1 ps `define POWER_UP_TIME_PERIOD 200 `define SOC_RESET_TIME_PERIOD 2000 `define SOC_SETUP_TIME_PERIOD 200*2001 `define SOC_CLOCK_PERIOD 12.5 `define FPGA_PROG_CLOCK_PERIOD 12.5 `define FPGA_CLOCK_PERIOD 12.5 module ccff_test_post_pnr_caravel_autocheck_top_tb; reg clock; reg RSTB; reg power1, power2; reg power3, power4; wire gpio; wire [37:0] mprj_io; // ----- Local wires for control ports of FPGA fabric ----- wire [0:0] pReset; reg [0:0] prog_clock_reg; wire [0:0] prog_clk; wire [0:0] prog_clock; wire [0:0] Test_en; wire [0:0] Reset; reg [0:0] op_clock_reg; wire [0:0] op_clk; wire [0:0] op_clock; reg [0:0] prog_reset; reg [0:0] greset; // ---- Configuration-chain head ----- reg [0:0] ccff_head; // ---- Configuration-chain tail ----- wire [0:0] ccff_tail; // ---- Scan-chain head ----- wire [0:0] sc_head; // ---- Scan-chain tail ----- wire [0:0] sc_tail; wire [0:0] IO_ISOL_N; // ----- Counters for error checking ----- integer num_prog_cycles = 0; integer num_errors = 0; integer num_checked_points = 0; // Indicate when SoC setup phase should be finished reg soc_setup_done = 0; // Indicate when configuration should be finished reg config_done = 0; initial begin config_done = 1'b0; soc_setup_done = 1'b0; end // ----- Begin raw programming clock signal generation ----- initial begin prog_clock_reg[0] = 1'b0; end always begin #(`FPGA_PROG_CLOCK_PERIOD) prog_clock_reg[0] = ~prog_clock_reg[0]; end // ----- End raw programming clock signal generation ----- // ----- Begin raw operating clock signal generation ----- initial begin op_clock_reg[0] = 1'b0; end // ----- End raw operating clock signal generation ----- // ----- Actual operating clock is triggered only when config_done is enabled ----- assign prog_clock[0] = prog_clock_reg[0] & (~prog_reset[0]); assign op_clock[0] = op_clock_reg[0]; // ----- Begin programming reset signal generation ----- initial begin prog_reset[0] = 1'b1; #(`SOC_SETUP_TIME_PERIOD + 2 * `FPGA_PROG_CLOCK_PERIOD) prog_reset[0] = 1'b0; end // ----- End programming reset signal generation ----- // ----- Begin operating reset signal generation ----- // ----- Reset signal is disabled always ----- initial begin greset[0] = 1'b1; end // ----- End operating reset signal generation ----- // ----- Begin connecting global ports of FPGA fabric to stimuli ----- assign op_clk[0] = op_clock[0]; assign prog_clk[0] = prog_clock[0]; assign pReset[0] = ~prog_reset[0]; assign Reset[0] = ~greset[0]; assign Test_en[0] = 1'b0; assign sc_head[0] = 1'b0; assign IO_ISOL_N[0] = ~greset; // ----- End connecting global ports of FPGA fabric to stimuli ----- assign mprj_io[0] = Test_en; assign mprj_io[1] = IO_ISOL_N; assign mprj_io[2] = Reset; assign mprj_io[3] = pReset; assign mprj_io[12] = ccff_head; assign mprj_io[25] = 1'b0; // Set FPGA to interface logic analyzer by default assign mprj_io[26] = sc_head; assign mprj_io[36] = op_clk; assign mprj_io[37] = prog_clk; assign sc_tail = mprj_io[11]; assign ccff_tail = mprj_io[35]; assign mprj_io[10:4] = {7{1'b0}}; assign mprj_io[24:13] = {12{1'b0}}; assign mprj_io[34:27] = {8{1'b0}}; // Generate a pulse after programming reset is disabled (in the 2nd clock // cycle). Then the head of configuration chain should be always zero always @(negedge prog_clock[0]) begin ccff_head = 1'b1; if (0 != num_prog_cycles) begin ccff_head = 1'b0; end end // ----- Count the number of programming cycles ------- always @(posedge prog_clock[0]) begin num_prog_cycles = num_prog_cycles + 1; // Indicate when configuration is suppose to end if (`FPGA_BITSTREAM_SIZE + 1 == num_prog_cycles) begin config_done = 1'b1; end // Check the ccff_tail when configuration is done if (1'b1 == config_done) begin // The tail should spit a pulse after configuration is done // So it should be at logic '1' and then pulled down to logic '0' if (0 == num_checked_points) begin if (ccff_tail !== 1'b1) begin $display("Error: ccff_tail = %b", sc_tail); num_errors = num_errors + 1; end end if (1 <= num_checked_points) begin if (ccff_tail !== 1'b0) begin $display("Error: ccff_tail = %b", sc_tail); num_errors = num_errors + 1; end end num_checked_points = num_checked_points + 1; end if (2 < num_checked_points) begin $display("Simulation finish with %d errors", num_errors); // End simulation $finish; end end // External clock is used by default. Make this artificially fast for the // simulation. Normally this would be a slow clock and the digital PLL // would be the fast clock. always #(`SOC_CLOCK_PERIOD) clock <= (clock === 1'b0); initial begin clock = 0; end initial begin RSTB <= 1'b0; soc_setup_done <= 1'b1; #(`SOC_RESET_TIME_PERIOD); RSTB <= 1'b1; // Release reset soc_setup_done <= 1'b1; // We can start scff test end initial begin // Power-up sequence power1 <= 1'b0; power2 <= 1'b0; power3 <= 1'b0; power4 <= 1'b0; #(`POWER_UP_TIME_PERIOD); power1 <= 1'b1; #(`POWER_UP_TIME_PERIOD); power2 <= 1'b1; #(`POWER_UP_TIME_PERIOD); power3 <= 1'b1; #(`POWER_UP_TIME_PERIOD); power4 <= 1'b1; end wire flash_csb; wire flash_clk; wire flash_io0; wire flash_io1; wire VDD3V3 = power1; wire VDD1V8 = power2; wire USER_VDD3V3 = power3; wire USER_VDD1V8 = power4; wire VSS = 1'b0; caravel uut ( .vddio (VDD3V3), .vssio (VSS), .vdda (VDD3V3), .vssa (VSS), .vccd (VDD1V8), .vssd (VSS), .vdda1 (USER_VDD3V3), .vdda2 (USER_VDD3V3), .vssa1 (VSS), .vssa2 (VSS), .vccd1 (USER_VDD1V8), .vccd2 (USER_VDD1V8), .vssd1 (VSS), .vssd2 (VSS), .clock (clock), .gpio (gpio), .mprj_io (mprj_io), .flash_csb(flash_csb), .flash_clk(flash_clk), .flash_io0(flash_io0), .flash_io1(flash_io1), .resetb (RSTB) ); spiflash #( .FILENAME("/research/ece/lnis/USERS/tang/github/skywater-openfpga/TESTBENCH/caravel_dv/ccff_test/ccff_test_caravel.hex") ) spiflash ( .csb(flash_csb), .clk(flash_clk), .io0(flash_io0), .io1(flash_io1), .io2(), // not used .io3() // not used ); endmodule