mirror of
https://gitlab.com/hyperglitch/jellyfish.git
synced 2025-12-24 06:36:47 +00:00
- testbenches updated with TB_DEPS directive for granular dependency definition - async_fifo added for transferring ADC data to QSPI - qspi reads fixed - adc_ctrl properly sampling the ADC - DAC tested and working - periodic ADC trigger added
447 lines
8.9 KiB
Systemverilog
447 lines
8.9 KiB
Systemverilog
`timescale 1ns / 1ps
|
|
|
|
// SPDX-FileCopyrightText: 2025 Igor Brkic <igor@hyperglitch.com>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
//TB_DEPS: src/qspi_decoder.v src/async_fifo.v test/_module_sb_io.sv
|
|
|
|
// 1 command line
|
|
// 4 address lines
|
|
// 2 dummy cycles
|
|
// 8 data lines
|
|
module qspi_decoder_tb;
|
|
|
|
localparam ADDRESS_WIDTH = 24;
|
|
localparam ADDRESS_LINES = 4;
|
|
localparam COMMAND_WIDTH = 8;
|
|
localparam COMMAND_LINES = 1;
|
|
localparam DUMMY_CYCLES = 2;
|
|
localparam DATA_WIDTH = 8;
|
|
localparam DATA_LINES = 4;
|
|
localparam DATA_BANKS = 2;
|
|
|
|
reg i_rst;
|
|
reg i_ncs;
|
|
reg clk_main;
|
|
reg clk_qspi;
|
|
|
|
reg ext_i_bk1_io0;
|
|
reg ext_i_bk1_io1;
|
|
reg ext_i_bk1_io2;
|
|
reg ext_i_bk1_io3;
|
|
reg ext_i_bk2_io0;
|
|
reg ext_i_bk2_io1;
|
|
reg ext_i_bk2_io2;
|
|
reg ext_i_bk2_io3;
|
|
|
|
wire i_bk1_io0;
|
|
wire i_bk1_io1;
|
|
wire i_bk1_io2;
|
|
wire i_bk1_io3;
|
|
wire i_bk2_io0;
|
|
wire i_bk2_io1;
|
|
wire i_bk2_io2;
|
|
wire i_bk2_io3;
|
|
|
|
assign i_bk1_io0 = dut.oe ? 1'bz : ext_i_bk1_io0;
|
|
assign i_bk1_io1 = dut.oe ? 1'bz : ext_i_bk1_io1;
|
|
assign i_bk1_io2 = dut.oe ? 1'bz : ext_i_bk1_io2;
|
|
assign i_bk1_io3 = dut.oe ? 1'bz : ext_i_bk1_io3;
|
|
assign i_bk2_io0 = dut.oe ? 1'bz : ext_i_bk2_io0;
|
|
assign i_bk2_io1 = dut.oe ? 1'bz : ext_i_bk2_io1;
|
|
assign i_bk2_io2 = dut.oe ? 1'bz : ext_i_bk2_io2;
|
|
assign i_bk2_io3 = dut.oe ? 1'bz : ext_i_bk2_io3;
|
|
|
|
|
|
reg o_cmd_rdy;
|
|
reg o_addr_rdy;
|
|
reg o_data_rdy;
|
|
reg [ADDRESS_WIDTH-1:0] o_address;
|
|
reg [COMMAND_WIDTH-1:0] o_command;
|
|
wire [DATA_WIDTH*DATA_BANKS-1:0] o_data;
|
|
|
|
qspi_decoder #(
|
|
.ADDRESS_WIDTH(ADDRESS_WIDTH),
|
|
.ADDRESS_LINES(ADDRESS_LINES),
|
|
.COMMAND_WIDTH(COMMAND_WIDTH),
|
|
.COMMAND_LINES(COMMAND_LINES),
|
|
.DUMMY_CYCLES(DUMMY_CYCLES),
|
|
.DATA_WIDTH(DATA_WIDTH),
|
|
.DATA_LINES(DATA_LINES),
|
|
.DATA_BANKS(DATA_BANKS)
|
|
) dut (
|
|
.i_rst(i_rst),
|
|
.i_ncs(i_ncs),
|
|
.i_clk(clk_qspi),
|
|
.i_main_clk(clk_main),
|
|
.i_bk1_io0(i_bk1_io0),
|
|
.i_bk1_io1(i_bk1_io1),
|
|
.i_bk1_io2(i_bk1_io2),
|
|
.i_bk1_io3(i_bk1_io3),
|
|
.i_bk2_io0(i_bk2_io0),
|
|
.i_bk2_io1(i_bk2_io1),
|
|
.i_bk2_io2(i_bk2_io2),
|
|
.i_bk2_io3(i_bk2_io3),
|
|
.o_cmd_rdy(o_cmd_rdy),
|
|
.o_addr_rdy(o_addr_rdy),
|
|
.o_data_rdy(o_data_rdy),
|
|
.o_address(o_address),
|
|
.o_command(o_command),
|
|
.o_data(o_data)
|
|
);
|
|
|
|
localparam PERIOD_QSPI_CLK = 50;
|
|
localparam PERIOD_QSPI_CLK_HALF = PERIOD_QSPI_CLK/2;
|
|
localparam PERIOD_MAIN_CLK = 41;
|
|
|
|
// generate clock
|
|
initial begin
|
|
clk_qspi = 0;
|
|
#25;
|
|
forever #PERIOD_QSPI_CLK clk_qspi = ~clk_qspi; // 20MHz
|
|
end
|
|
|
|
initial begin
|
|
clk_main = 0;
|
|
#17; // phase offset
|
|
forever #PERIOD_MAIN_CLK clk_main = ~clk_main; // 24.39MHz
|
|
end
|
|
|
|
// test sequence
|
|
initial begin
|
|
i_ncs = 0;
|
|
#5;
|
|
i_ncs = 1;
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
|
|
// reset
|
|
i_rst = 1;
|
|
#PERIOD_MAIN_CLK;
|
|
i_rst = 0;
|
|
#PERIOD_MAIN_CLK;
|
|
|
|
// chip select
|
|
i_ncs = 0;
|
|
#100;
|
|
|
|
// send command over io0 line
|
|
ext_i_bk1_io0 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
assert(o_command == 8'hAD);
|
|
$display("o_command: %x", o_command);
|
|
|
|
// send address over all four lines
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 1;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 1;
|
|
ext_i_bk1_io3 = 0;
|
|
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 1;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 1;
|
|
ext_i_bk1_io3 = 0;
|
|
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 1;
|
|
ext_i_bk2_io2 = 1;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 1;
|
|
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 1;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 1;
|
|
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 1;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
assert(o_address == 24'h0056AA);
|
|
|
|
// dummy cycles
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// send data over 8 lines
|
|
|
|
// byte 0
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 1;
|
|
ext_i_bk1_io3 = 1;
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 1
|
|
ext_i_bk1_io0 = 1;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 2
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 3
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 1;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 4
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 5
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 1;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 1;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 6
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 7
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 1;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 1;
|
|
ext_i_bk2_io2 = 1;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 8
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 1;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 9
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 10
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 1;
|
|
ext_i_bk1_io3 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 1;
|
|
ext_i_bk2_io3 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 11
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 1;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 12
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 13
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 1;
|
|
ext_i_bk1_io3 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 1;
|
|
ext_i_bk2_io3 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 14
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// byte 15
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 1;
|
|
ext_i_bk1_io2 = 1;
|
|
ext_i_bk1_io3 = 1;
|
|
ext_i_bk2_io0 = 1;
|
|
ext_i_bk2_io1 = 1;
|
|
ext_i_bk2_io2 = 1;
|
|
ext_i_bk2_io3 = 1;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
i_ncs = 1;
|
|
ext_i_bk1_io0 = 0;
|
|
ext_i_bk1_io1 = 0;
|
|
ext_i_bk1_io2 = 0;
|
|
ext_i_bk1_io3 = 0;
|
|
ext_i_bk2_io0 = 0;
|
|
ext_i_bk2_io1 = 0;
|
|
ext_i_bk2_io2 = 0;
|
|
ext_i_bk2_io3 = 0;
|
|
#20;
|
|
|
|
|
|
$finish;
|
|
end
|
|
|
|
initial begin
|
|
$dumpfile("build/qspi_decoder_tb_1c4a8d.vcd");
|
|
$dumpvars(0, qspi_decoder_tb);
|
|
end
|
|
|
|
endmodule
|