| // SPDX-FileCopyrightText: 2020 Efabless Corporation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| `default_nettype none |
| |
| `timescale 1 ns / 1 ps |
| |
| `include "caravel.v" |
| `include "spiflash.v" |
| `include "fabric_netlists.v" |
| `include "tie_array.v" |
| |
| `define FPGA_BITSTREAM_SIZE 29696 |
| |
| `define POWER_UP_TIME_PERIOD 200 |
| `define SOC_SETUP_TIME_PERIOD 2000 |
| `define SOC_CLOCK_PERIOD 12.5 |
| `define FPGA_PROG_CLOCK_PERIOD 12.5 |
| `define FPGA_CLOCK_PERIOD 12.5 |
| |
| module io_ports; |
| 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] = prog_clock ; //1'b1; |
| 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_SETUP_TIME_PERIOD); |
| RSTB <= 1'b1; // Release reset |
| soc_setup_done <= 1'b1; // We can start scff test |
| end |
| |
| initial begin |
| $dumpfile("io_ports.vcd"); |
| $dumpvars(0, io_ports); |
| repeat (`FPGA_BITSTREAM_SIZE + 10) @(posedge prog_clk); |
| $display("%c[1;31m",27); |
| $display ("Monitor: Timeout, Test Mega-Project IO (ccff_test) Failed"); |
| $display("%c[0m",27); |
| $finish; |
| 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("io_ports.hex") |
| ) spiflash ( |
| .csb(flash_csb), |
| .clk(flash_clk), |
| .io0(flash_io0), |
| .io1(flash_io1), |
| .io2(), // not used |
| .io3() // not used |
| ); |
| |
| endmodule |
| `default_nettype wire |