mirror of
https://gitlab.com/hyperglitch/jellyfish.git
synced 2025-12-21 22:15:23 +00:00
289 lines
6.6 KiB
Systemverilog
289 lines
6.6 KiB
Systemverilog
// SPDX-FileCopyrightText: 2025 Igor Brkic <igor@hyperglitch.com>
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
// Define timescale
|
|
`timescale 1 us / 10 ps
|
|
|
|
//TB_DEPS: src/adc_ctrl.v src/async_fifo.v src/qspi_decoder.v test/_module_sb_io.sv
|
|
|
|
|
|
module sampling_tb();
|
|
|
|
localparam QSPI_ADDRESS_WIDTH = 24;
|
|
localparam QSPI_ADDRESS_LINES = 4;
|
|
localparam QSPI_COMMAND_WIDTH = 8;
|
|
localparam QSPI_COMMAND_LINES = 1;
|
|
localparam QSPI_DUMMY_CYCLES = 2;
|
|
localparam QSPI_DATA_WIDTH = 8;
|
|
localparam QSPI_DATA_LINES = 4;
|
|
localparam QSPI_DATA_BANKS = 2;
|
|
|
|
localparam FIFO_DATA_WIDTH = 16;
|
|
localparam FIFO_ADDR_WIDTH = 8;
|
|
|
|
localparam PERIOD_QSPI_CLK = 50;
|
|
localparam PERIOD_QSPI_CLK_HALF = PERIOD_QSPI_CLK/2;
|
|
localparam PERIOD_MAIN_CLK = 41;
|
|
|
|
|
|
reg rst;
|
|
reg qspi_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 = _qspi_decoder.oe ? 1'bz : ext_i_bk1_io0;
|
|
assign i_bk1_io1 = _qspi_decoder.oe ? 1'bz : ext_i_bk1_io1;
|
|
assign i_bk1_io2 = _qspi_decoder.oe ? 1'bz : ext_i_bk1_io2;
|
|
assign i_bk1_io3 = _qspi_decoder.oe ? 1'bz : ext_i_bk1_io3;
|
|
assign i_bk2_io0 = _qspi_decoder.oe ? 1'bz : ext_i_bk2_io0;
|
|
assign i_bk2_io1 = _qspi_decoder.oe ? 1'bz : ext_i_bk2_io1;
|
|
assign i_bk2_io2 = _qspi_decoder.oe ? 1'bz : ext_i_bk2_io2;
|
|
assign i_bk2_io3 = _qspi_decoder.oe ? 1'bz : ext_i_bk2_io3;
|
|
|
|
wire qspi_cmd_rdy;
|
|
wire qspi_addr_rdy;
|
|
wire qspi_data_rdy;
|
|
wire qspi_data_done;
|
|
|
|
wire [QSPI_ADDRESS_WIDTH-1:0] qspi_address;
|
|
wire [QSPI_COMMAND_WIDTH-1:0] qspi_command;
|
|
wire [QSPI_DATA_WIDTH*QSPI_DATA_BANKS-1:0] qspi_data;
|
|
|
|
reg [QSPI_DATA_WIDTH*QSPI_DATA_BANKS-1:0] qspi_data_in = 16'h1234;
|
|
wire [QSPI_DATA_WIDTH*QSPI_DATA_BANKS-1:0] qspi_data_in_wire;
|
|
|
|
// generate clocks
|
|
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
|
|
|
|
|
|
|
|
|
|
reg EXT_GPIO_0 = 1'b0;
|
|
reg EXT_GPIO_1 = 1'b0;
|
|
reg EXT_GPIO_2 = 1'b0;
|
|
reg EXT_GPIO_3 = 1'b0;
|
|
reg EXT_GPIO_4 = 1'b0;
|
|
|
|
wire ADC_NCS1, ADC_NCS2, ADC_SDI, ADC_SCK, ADC_NRST, ADC_CONVST;
|
|
reg ADC_SDO0, ADC_SDO1, ADC_SDO2, ADC_SDO3, ADC_SDO4, ADC_SDO5, ADC_SDO6, ADC_SDO7;
|
|
reg ADC_RDY1, ADC_RDY2;
|
|
|
|
wire LED1;
|
|
reg ADC_MUX_SW;
|
|
|
|
|
|
|
|
|
|
wire [15:0] adc_data;
|
|
wire adc_data_ready;
|
|
reg adc_trigger = 1'b0;
|
|
|
|
wire data_fifo_full;
|
|
wire data_fifo_empty;
|
|
|
|
adc_ctrl _adc_ctrl (
|
|
.i_rst(rst),
|
|
.i_clk(clk_main),
|
|
.o_ncs1(ADC_NCS1),
|
|
.o_ncs2(ADC_NCS2),
|
|
.o_sdi(ADC_SDI),
|
|
.i_sdo0(ADC_SDO0),
|
|
.i_sdo1(ADC_SDO1),
|
|
.i_sdo2(ADC_SDO2),
|
|
.i_sdo3(ADC_SDO3),
|
|
.i_sdo4(ADC_SDO4),
|
|
.i_sdo5(ADC_SDO5),
|
|
.i_sdo6(ADC_SDO6),
|
|
.i_sdo7(ADC_SDO7),
|
|
.o_sck(ADC_SCK),
|
|
.o_nrst(ADC_NRST),
|
|
.o_convst(ADC_CONVST),
|
|
.i_rdy1(ADC_RDY1),
|
|
.i_rdy2(ADC_RDY2),
|
|
.o_mux_sw(ADC_MUX_SW),
|
|
.i_trigger(adc_trigger),
|
|
|
|
.o_data(adc_data),
|
|
.o_data_ready(adc_data_ready),
|
|
.i_data_fifo_full(data_fifo_full),
|
|
.dbgled(LED1),
|
|
.ext_gpio({EXT_GPIO_0, EXT_GPIO_1, EXT_GPIO_2, EXT_GPIO_3, EXT_GPIO_4})
|
|
);
|
|
|
|
qspi_decoder #(
|
|
.ADDRESS_WIDTH(QSPI_ADDRESS_WIDTH),
|
|
.ADDRESS_LINES(QSPI_ADDRESS_LINES),
|
|
.COMMAND_WIDTH(QSPI_COMMAND_WIDTH),
|
|
.COMMAND_LINES(QSPI_COMMAND_LINES),
|
|
.DUMMY_CYCLES(QSPI_DUMMY_CYCLES),
|
|
.DATA_WIDTH(QSPI_DATA_WIDTH),
|
|
.DATA_LINES(QSPI_DATA_LINES),
|
|
.DATA_BANKS(QSPI_DATA_BANKS)
|
|
) _qspi_decoder (
|
|
.i_rst(rst),
|
|
.i_ncs(qspi_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(qspi_cmd_rdy),
|
|
.o_addr_rdy(qspi_addr_rdy),
|
|
.o_data_rdy(qspi_data_rdy),
|
|
.o_address(qspi_address),
|
|
.o_command(qspi_command),
|
|
.o_data(qspi_data),
|
|
.i_data(qspi_data_in),
|
|
.i_fifo_wr_en(adc_data_ready),
|
|
.i_fifo_wr_data(adc_data),
|
|
.o_data_fifo_full(data_fifo_full),
|
|
.o_data_fifo_empty(data_fifo_empty)
|
|
);
|
|
|
|
|
|
initial begin
|
|
rst = 1;
|
|
qspi_ncs = 1;
|
|
#PERIOD_MAIN_CLK;
|
|
rst = 0;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
qspi_ncs = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
|
|
// trigger ADC
|
|
adc_trigger = 1'b1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
adc_trigger = 1'b0;
|
|
ADC_RDY1 = 1'b1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
ADC_RDY1 = 1'b0;
|
|
#(PERIOD_MAIN_CLK*160);
|
|
|
|
// trigger ADC once more
|
|
adc_trigger = 1'b1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
adc_trigger = 1'b0;
|
|
ADC_RDY1 = 1'b1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
ADC_RDY1 = 1'b0;
|
|
#(PERIOD_MAIN_CLK*160);
|
|
|
|
// and a third time
|
|
adc_trigger = 1'b1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
adc_trigger = 1'b0;
|
|
ADC_RDY1 = 1'b1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
ADC_RDY1 = 1'b0;
|
|
#(PERIOD_MAIN_CLK*160);
|
|
|
|
|
|
|
|
adc_trigger = 1'b1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
adc_trigger = 1'b0;
|
|
ADC_RDY1 = 1'b1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
ADC_RDY1 = 1'b0;
|
|
|
|
// send data to the MCU
|
|
// set qspi decoder to dummy wait state and let it switch to DATA_WRITE
|
|
_qspi_decoder.current_state = _qspi_decoder.DUMMY_WAIT;
|
|
_qspi_decoder.dummy_counter = 0;
|
|
_qspi_decoder.command = 8'h01;
|
|
#(PERIOD_QSPI_CLK*30);
|
|
#(PERIOD_QSPI_CLK/2);
|
|
|
|
qspi_ncs = 1;
|
|
#PERIOD_MAIN_CLK;
|
|
#PERIOD_MAIN_CLK;
|
|
qspi_ncs = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
|
|
// send data to the MCU
|
|
// set qspi decoder to dummy wait state and let it switch to DATA_WRITE
|
|
_qspi_decoder.current_state = _qspi_decoder.DUMMY_WAIT;
|
|
_qspi_decoder.dummy_counter = 0;
|
|
_qspi_decoder.command = 8'h01;
|
|
#(PERIOD_QSPI_CLK*43);
|
|
qspi_ncs = 1;
|
|
|
|
#(PERIOD_QSPI_CLK*10);
|
|
qspi_ncs = 0;
|
|
#PERIOD_QSPI_CLK;
|
|
#PERIOD_QSPI_CLK;
|
|
|
|
// send data to the MCU
|
|
// set qspi decoder to dummy wait state and let it switch to DATA_WRITE
|
|
_qspi_decoder.current_state = _qspi_decoder.DUMMY_WAIT;
|
|
_qspi_decoder.dummy_counter = 0;
|
|
_qspi_decoder.command = 8'h01;
|
|
#(PERIOD_QSPI_CLK*38);
|
|
|
|
|
|
#(PERIOD_QSPI_CLK*25);
|
|
|
|
|
|
#1000;
|
|
|
|
$finish;
|
|
end
|
|
|
|
|
|
|
|
initial begin
|
|
$dumpfile("build/sampling_tb.vcd");
|
|
$dumpvars(0, sampling_tb);
|
|
end
|
|
endmodule
|