blob: 9ceca81017df7f979503acbfc725bff9e9f35272 [file] [log] [blame]
// 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