even more fixes and tests

This commit is contained in:
Mateusz Faderewski 2024-07-08 17:00:49 +02:00
parent 11372e0910
commit 64f78e040a
16 changed files with 442 additions and 257 deletions

View File

@ -15,6 +15,9 @@
<Source name="../../rtl/sd/sd_scb.sv" type="Verilog" type_short="Verilog"> <Source name="../../rtl/sd/sd_scb.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/> <Options VerilogStandard="System Verilog"/>
</Source> </Source>
<Source name="../../rtl/usb/usb_scb.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/>
</Source>
<Source name="../../rtl/fifo/fifo_bus.sv" type="Verilog" type_short="Verilog"> <Source name="../../rtl/fifo/fifo_bus.sv" type="Verilog" type_short="Verilog">
<Options VerilogStandard="System Verilog"/> <Options VerilogStandard="System Verilog"/>
</Source> </Source>

View File

@ -214,7 +214,7 @@ LOCATE COMP "usb_miso" SITE "10" ;
LOCATE COMP "usb_pwrsav" SITE "2" ; LOCATE COMP "usb_pwrsav" SITE "2" ;
SYSCONFIG SDM_PORT=DISABLE I2C_PORT=ENABLE ; SYSCONFIG SDM_PORT=DISABLE I2C_PORT=ENABLE ;
VOLTAGE 3.300 V; VOLTAGE 3.300 V;
FREQUENCY NET "clk" 100.000000 MHz PAR_ADJ 20.000000 ; FREQUENCY NET "clk" 100.000000 MHz ;
BLOCK PATH TO PORT "mcu_int" ; BLOCK PATH TO PORT "mcu_int" ;
BLOCK PATH TO PORT "n64_irq" ; BLOCK PATH TO PORT "n64_irq" ;
BLOCK PATH FROM PORT "usb_pwrsav" ; BLOCK PATH FROM PORT "usb_pwrsav" ;

View File

@ -1,35 +1,29 @@
interface fifo_bus (); interface fifo_bus ();
logic rx_empty; logic rx_empty;
logic rx_almost_empty;
logic rx_read; logic rx_read;
logic [7:0] rx_rdata; logic [7:0] rx_rdata;
logic tx_full; logic tx_full;
logic tx_almost_full;
logic tx_write; logic tx_write;
logic [7:0] tx_wdata; logic [7:0] tx_wdata;
modport controller ( modport controller (
input rx_empty, input rx_empty,
input rx_almost_empty,
output rx_read, output rx_read,
input rx_rdata, input rx_rdata,
input tx_full, input tx_full,
input tx_almost_full,
output tx_write, output tx_write,
output tx_wdata output tx_wdata
); );
modport fifo ( modport fifo (
output rx_empty, output rx_empty,
output rx_almost_empty,
input rx_read, input rx_read,
output rx_rdata, output rx_rdata,
output tx_full, output tx_full,
output tx_almost_full,
input tx_write, input tx_write,
input tx_wdata input tx_wdata
); );

View File

@ -11,16 +11,12 @@ module fifo_junction (
dev_bus.tx_wdata = cfg_bus.tx_write ? cfg_bus.tx_wdata : dma_bus.tx_wdata; dev_bus.tx_wdata = cfg_bus.tx_write ? cfg_bus.tx_wdata : dma_bus.tx_wdata;
cfg_bus.rx_empty = dev_bus.rx_empty; cfg_bus.rx_empty = dev_bus.rx_empty;
cfg_bus.rx_almost_empty = dev_bus.rx_almost_empty;
cfg_bus.rx_rdata = dev_bus.rx_rdata; cfg_bus.rx_rdata = dev_bus.rx_rdata;
cfg_bus.tx_full = dev_bus.tx_full; cfg_bus.tx_full = dev_bus.tx_full;
cfg_bus.tx_almost_full = dev_bus.tx_almost_full;
dma_bus.rx_empty = dev_bus.rx_empty; dma_bus.rx_empty = dev_bus.rx_empty;
dma_bus.rx_almost_empty = dev_bus.rx_almost_empty;
dma_bus.rx_rdata = dev_bus.rx_rdata; dma_bus.rx_rdata = dev_bus.rx_rdata;
dma_bus.tx_full = dev_bus.tx_full; dma_bus.tx_full = dev_bus.tx_full;
dma_bus.tx_almost_full = dev_bus.tx_almost_full;
end end
endmodule endmodule

View File

@ -22,20 +22,22 @@ module memory_sdram (
// in nanoseconds // in nanoseconds
localparam real T_INIT = 100_000.0; localparam real T_INIT = 100_000.0;
localparam real T_RC = 60.0;
localparam real T_RP = 15.0;
localparam real T_RCD = 15.0;
localparam real T_MRD = 14.0; localparam real T_MRD = 14.0;
localparam real T_RAS = 37.0;
localparam real T_RC = 60.0;
localparam real T_RCD = 15.0;
localparam real T_REF = 7_812.5; localparam real T_REF = 7_812.5;
localparam real T_RP = 15.0;
localparam real T_CLK = (1.0 / FREQUENCY) * 1_000_000_000.0; localparam real T_CLK = (1.0 / FREQUENCY) * 1_000_000_000.0;
const bit [13:0] C_INIT = 14'(int'($ceil(T_INIT / T_CLK))); const bit [13:0] C_INIT = 14'(int'($ceil(T_INIT / T_CLK)));
const bit [4:0] C_RC = 5'(int'($ceil(T_RC / T_CLK)));
const bit [4:0] C_RP = 5'(int'($ceil(T_RP / T_CLK)));
const bit [4:0] C_RCD = 5'(int'($ceil(T_RCD / T_CLK)));
const bit [4:0] C_MRD = 5'(int'($ceil(T_MRD / T_CLK))); const bit [4:0] C_MRD = 5'(int'($ceil(T_MRD / T_CLK)));
const bit [2:0] C_RAS = 3'(int'($ceil(T_RAS / T_CLK)));
const bit [4:0] C_RC = 5'(int'($ceil(T_RC / T_CLK)));
const bit [4:0] C_RCD = 5'(int'($ceil(T_RCD / T_CLK)));
const bit [13:0] C_REF = 14'(int'($ceil(T_REF / T_CLK))); const bit [13:0] C_REF = 14'(int'($ceil(T_REF / T_CLK)));
const bit [4:0] C_RP = 5'(int'($ceil(T_RP / T_CLK)));
const bit [4:0] INIT_PRECHARGE = 5'd0; const bit [4:0] INIT_PRECHARGE = 5'd0;
const bit [4:0] INIT_REFRESH_1 = INIT_PRECHARGE + C_RP; const bit [4:0] INIT_REFRESH_1 = INIT_PRECHARGE + C_RP;
@ -139,8 +141,10 @@ module memory_sdram (
logic [13:0] refresh_counter; logic [13:0] refresh_counter;
logic [4:0] wait_counter; logic [4:0] wait_counter;
logic [2:0] precharge_counter;
logic powerup_done; logic powerup_done;
logic pending_refresh; logic pending_refresh;
logic precharge_valid;
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
refresh_counter <= refresh_counter + 1'd1; refresh_counter <= refresh_counter + 1'd1;
@ -170,6 +174,17 @@ module memory_sdram (
if (state != next_state) begin if (state != next_state) begin
wait_counter <= 5'd0; wait_counter <= 5'd0;
end end
precharge_counter <= precharge_counter + 1'd1;
if (precharge_counter >= C_RAS - 2'd2) begin
precharge_valid <= 1'b1;
end
if (sdram_next_cmd == CMD_ACT) begin
precharge_counter <= 3'd0;
precharge_valid <= 1'b0;
end
end end
logic [(CAS_LATENCY):0] read_cmd_ack_delay; logic [(CAS_LATENCY):0] read_cmd_ack_delay;
@ -228,14 +243,14 @@ module memory_sdram (
end end
S_ACTIVE: begin S_ACTIVE: begin
if (pending_refresh) begin if (pending_refresh && precharge_valid) begin
next_state = S_PRECHARGE; next_state = S_PRECHARGE;
sdram_next_cmd = CMD_PRE; sdram_next_cmd = CMD_PRE;
end else if (mem_bus.request) begin end else if (mem_bus.request) begin
if (request_in_current_active_bank_row) begin if (request_in_current_active_bank_row) begin
next_state = S_BUSY; next_state = S_BUSY;
sdram_next_cmd = mem_bus.write ? CMD_WRITE : CMD_READ; sdram_next_cmd = mem_bus.write ? CMD_WRITE : CMD_READ;
end else begin end else if (precharge_valid) begin
next_state = S_PRECHARGE; next_state = S_PRECHARGE;
sdram_next_cmd = CMD_PRE; sdram_next_cmd = CMD_PRE;
end end

View File

@ -36,12 +36,10 @@ module sd_dat (
// FIFO // FIFO
logic rx_full; logic rx_full;
logic rx_almost_full;
logic rx_write; logic rx_write;
logic [7:0] rx_wdata; logic [7:0] rx_wdata;
logic tx_empty; logic tx_empty;
logic tx_almost_empty;
logic tx_read; logic tx_read;
logic [7:0] tx_rdata; logic [7:0] tx_rdata;
@ -50,12 +48,10 @@ module sd_dat (
.reset(reset || sd_scb.dat_fifo_flush), .reset(reset || sd_scb.dat_fifo_flush),
.empty(fifo_bus.rx_empty), .empty(fifo_bus.rx_empty),
.almost_empty(fifo_bus.rx_almost_empty),
.read(fifo_bus.rx_read), .read(fifo_bus.rx_read),
.rdata(fifo_bus.rx_rdata), .rdata(fifo_bus.rx_rdata),
.full(rx_full), .full(rx_full),
.almost_full(rx_almost_full),
.write(rx_write), .write(rx_write),
.wdata(rx_wdata), .wdata(rx_wdata),
@ -67,12 +63,10 @@ module sd_dat (
.reset(reset || sd_scb.dat_fifo_flush), .reset(reset || sd_scb.dat_fifo_flush),
.empty(tx_empty), .empty(tx_empty),
.almost_empty(tx_almost_empty),
.read(tx_read), .read(tx_read),
.rdata(tx_rdata), .rdata(tx_rdata),
.full(fifo_bus.tx_full), .full(fifo_bus.tx_full),
.almost_full(fifo_bus.tx_almost_full),
.write(fifo_bus.tx_write), .write(fifo_bus.tx_write),
.wdata(fifo_bus.tx_wdata), .wdata(fifo_bus.tx_wdata),

View File

@ -1,42 +1,3 @@
interface usb_scb ();
logic fifo_flush;
logic fifo_flush_busy;
logic write_buffer_flush;
logic [10:0] rx_count;
logic [10:0] tx_count;
logic pwrsav;
logic reset_state;
logic reset_on_ack;
logic reset_off_ack;
modport controller (
output fifo_flush,
input fifo_flush_busy,
output write_buffer_flush,
input rx_count,
input tx_count,
input pwrsav,
input reset_state,
output reset_on_ack,
output reset_off_ack
);
modport usb (
input fifo_flush,
output fifo_flush_busy,
input write_buffer_flush,
output rx_count,
output tx_count,
output pwrsav,
output reset_state,
input reset_on_ack,
input reset_off_ack
);
endinterface
module usb_ft1248 ( module usb_ft1248 (
input clk, input clk,
input reset, input reset,
@ -53,12 +14,10 @@ module usb_ft1248 (
); );
logic rx_full; logic rx_full;
logic rx_almost_full; logic rx_write_delayed;
logic rx_write;
logic [7:0] rx_wdata; logic [7:0] rx_wdata;
logic tx_empty; logic tx_empty;
logic tx_almost_empty;
logic tx_read; logic tx_read;
logic [7:0] tx_rdata; logic [7:0] tx_rdata;
@ -69,13 +28,11 @@ module usb_ft1248 (
.reset(reset || fifo_flush), .reset(reset || fifo_flush),
.empty(fifo_bus.rx_empty), .empty(fifo_bus.rx_empty),
.almost_empty(fifo_bus.rx_almost_empty),
.read(fifo_bus.rx_read), .read(fifo_bus.rx_read),
.rdata(fifo_bus.rx_rdata), .rdata(fifo_bus.rx_rdata),
.full(rx_full), .full(rx_full),
.almost_full(rx_almost_full), .write(rx_write_delayed),
.write(rx_write),
.wdata(rx_wdata), .wdata(rx_wdata),
.count(usb_scb.rx_count) .count(usb_scb.rx_count)
@ -86,12 +43,10 @@ module usb_ft1248 (
.reset(reset || fifo_flush), .reset(reset || fifo_flush),
.empty(tx_empty), .empty(tx_empty),
.almost_empty(tx_almost_empty),
.read(tx_read), .read(tx_read),
.rdata(tx_rdata), .rdata(tx_rdata),
.full(fifo_bus.tx_full), .full(fifo_bus.tx_full),
.almost_full(fifo_bus.tx_almost_full),
.write(fifo_bus.tx_write), .write(fifo_bus.tx_write),
.wdata(fifo_bus.tx_wdata), .wdata(fifo_bus.tx_wdata),
@ -145,6 +100,8 @@ module usb_ft1248 (
e_cmd cmd; e_cmd cmd;
e_cmd next_cmd; e_cmd next_cmd;
logic [3:0] phase; logic [3:0] phase;
logic rx_write;
logic last_rx_failed;
logic last_tx_failed; logic last_tx_failed;
logic reset_reply; logic reset_reply;
logic [4:0] modem_status_counter; logic [4:0] modem_status_counter;
@ -158,6 +115,8 @@ module usb_ft1248 (
usb_scb.pwrsav <= !ft_pwrsav; usb_scb.pwrsav <= !ft_pwrsav;
fifo_flush <= 1'b0; fifo_flush <= 1'b0;
rx_write_delayed <= rx_write;
phase <= {phase[2:0], phase[3]}; phase <= {phase[2:0], phase[3]};
if (state == STATE_IDLE) begin if (state == STATE_IDLE) begin
phase <= 4'b0100; phase <= 4'b0100;
@ -166,6 +125,7 @@ module usb_ft1248 (
if (reset) begin if (reset) begin
usb_scb.fifo_flush_busy <= 1'b0; usb_scb.fifo_flush_busy <= 1'b0;
usb_scb.reset_state <= 1'b0; usb_scb.reset_state <= 1'b0;
last_rx_failed <= 1'b0;
last_tx_failed <= 1'b0; last_tx_failed <= 1'b0;
reset_reply <= 1'b0; reset_reply <= 1'b0;
modem_status_counter <= 5'd0; modem_status_counter <= 5'd0;
@ -195,9 +155,19 @@ module usb_ft1248 (
if (usb_scb.fifo_flush_busy) begin if (usb_scb.fifo_flush_busy) begin
usb_scb.fifo_flush_busy <= 1'b0; usb_scb.fifo_flush_busy <= 1'b0;
fifo_flush <= 1'b1; fifo_flush <= 1'b1;
last_rx_failed <= 1'b0;
last_tx_failed <= 1'b0;
end else if (last_rx_failed && !rx_full) begin
last_rx_failed <= 1'b0;
rx_write_delayed <= 1'b1;
end end
end end
if ((state == STATE_DATA) && (cmd == CMD_READ) && phase[3]) begin
rx_wdata <= ft_miosi_in;
last_rx_failed <= !ft_miso && rx_full;
end
if ((state == STATE_DATA) && (cmd == CMD_WRITE) && phase[3]) begin if ((state == STATE_DATA) && (cmd == CMD_WRITE) && phase[3]) begin
last_tx_failed <= ft_miso; last_tx_failed <= ft_miso;
end end
@ -262,8 +232,6 @@ module usb_ft1248 (
rx_write = 1'b0; rx_write = 1'b0;
tx_read = 1'b0; tx_read = 1'b0;
rx_wdata = ft_miosi_in;
if (!ft_miso && phase[3]) begin if (!ft_miso && phase[3]) begin
case (state) case (state)
STATE_STATUS: begin STATE_STATUS: begin
@ -273,13 +241,15 @@ module usb_ft1248 (
end end
STATE_DATA: begin STATE_DATA: begin
if (cmd == CMD_READ) begin if (cmd == CMD_READ && !rx_full) begin
rx_write = 1'b1; rx_write = 1'b1;
end end
if (cmd == CMD_WRITE && !tx_empty) begin if (cmd == CMD_WRITE && !tx_empty) begin
tx_read = 1'b1; tx_read = 1'b1;
end end
end end
default: begin end
endcase endcase
end end
end end
@ -340,7 +310,7 @@ module usb_ft1248 (
if (ft_miso) begin if (ft_miso) begin
next_state = STATE_DESELECT; next_state = STATE_DESELECT;
end else if (cmd == CMD_READ) begin end else if (cmd == CMD_READ) begin
if (rx_almost_full) begin if (rx_full) begin
next_state = STATE_DESELECT; next_state = STATE_DESELECT;
end end
end else if (cmd == CMD_WRITE) begin end else if (cmd == CMD_WRITE) begin

37
fw/rtl/usb/usb_scb.sv Normal file
View File

@ -0,0 +1,37 @@
interface usb_scb ();
logic fifo_flush;
logic fifo_flush_busy;
logic write_buffer_flush;
logic [10:0] rx_count;
logic [10:0] tx_count;
logic pwrsav;
logic reset_state;
logic reset_on_ack;
logic reset_off_ack;
modport controller (
output fifo_flush,
input fifo_flush_busy,
output write_buffer_flush,
input rx_count,
input tx_count,
input pwrsav,
input reset_state,
output reset_on_ack,
output reset_off_ack
);
modport usb (
input fifo_flush,
output fifo_flush_busy,
input write_buffer_flush,
output rx_count,
output tx_count,
output pwrsav,
output reset_state,
input reset_on_ack,
input reset_off_ack
);
endinterface

View File

@ -3,18 +3,19 @@ module fifo_8kb (
input reset, input reset,
output empty, output empty,
output almost_empty,
input read, input read,
output [7:0] rdata, output [7:0] rdata,
output full, output full,
output almost_full,
input write, input write,
input [7:0] wdata, input [7:0] wdata,
output logic [10:0] count output logic [10:0] count
); );
logic almost_empty;
logic almost_full;
fifo_8kb_lattice_generated fifo_8kb_lattice_generated_inst ( fifo_8kb_lattice_generated fifo_8kb_lattice_generated_inst (
.Data(wdata), .Data(wdata),
.WrClock(clk), .WrClock(clk),
@ -25,7 +26,7 @@ module fifo_8kb (
.RPReset(reset), .RPReset(reset),
.Q(rdata), .Q(rdata),
.Empty(empty), .Empty(empty),
.Full(full), .Full(full),
.AlmostEmpty(almost_empty), .AlmostEmpty(almost_empty),
.AlmostFull(almost_full) .AlmostFull(almost_full)
); );

View File

@ -1,4 +1,5 @@
RTL_DIR = ../rtl RTL_DIR = ../rtl
BENCHES_DIR = benches
MOCKS_DIR = mocks MOCKS_DIR = mocks
BUILD_DIR = build BUILD_DIR = build
SRC_DIRS = \ SRC_DIRS = \
@ -11,10 +12,11 @@ SRC_DIRS = \
$(RTL_DIR)/usb \ $(RTL_DIR)/usb \
$(RTL_DIR)/vendor \ $(RTL_DIR)/vendor \
$(RTL_DIR) \ $(RTL_DIR) \
$(MOCKS_DIR)/vendor \
$(MOCKS_DIR) $(MOCKS_DIR)
INC_DIRS = $(addprefix -I, $(SRC_DIRS)) INC_DIRS = $(addprefix -I, $(SRC_DIRS))
TEST_FILES = $(shell find "./" -not -path "$(BUILD_DIR)/*" -type f -name "*_tb.sv") TEST_FILES = $(shell find "./$(BENCHES_DIR)" -not -path "$(BUILD_DIR)/*" -type f -name "*_tb.sv")
TESTS = $(addprefix $(BUILD_DIR)/, $(basename $(TEST_FILES))) TESTS = $(addprefix $(BUILD_DIR)/, $(basename $(TEST_FILES)))
VERILATOR_FLAGS = --binary --trace --timescale 10ns/1ns -j --quiet $(INC_DIRS) VERILATOR_FLAGS = --binary --trace --timescale 10ns/1ns -j --quiet $(INC_DIRS)

View File

@ -41,11 +41,11 @@ module memory_dma_tb;
.transfer_length(transfer_length) .transfer_length(transfer_length)
); );
fifo_bus_mock #( fifo_bus_fifo_mock #(
.DEPTH(16), .DEPTH(16),
.FILL_RATE(16), .FILL_RATE(16),
.DRAIN_RATE(16) .DRAIN_RATE(16)
) fifo_bus_mock ( ) fifo_bus_fifo_mock (
.clk(clk), .clk(clk),
.reset(reset), .reset(reset),
@ -103,7 +103,7 @@ module memory_dma_tb;
#1; #1;
stop = 1'b0; stop = 1'b0;
#99; #165;
start = 1'b1; start = 1'b1;
direction = 1'b1; direction = 1'b1;

View File

@ -0,0 +1,119 @@
module usb_ft1248_tb;
logic clk;
logic reset;
usb_scb usb_scb ();
fifo_bus fifo_bus ();
logic usb_pwrsav;
logic usb_clk;
logic usb_cs;
logic usb_miso;
logic [7:0] usb_miosi;
usb_ft1248 usb_ft1248 (
.clk(clk),
.reset(reset),
.usb_scb(usb_scb),
.fifo_bus(fifo_bus),
.usb_pwrsav(usb_pwrsav),
.usb_clk(usb_clk),
.usb_cs(usb_cs),
.usb_miso(usb_miso),
.usb_miosi(usb_miosi)
);
initial begin
clk = 1'b0;
forever begin
clk = ~clk; #0.5;
end
end
initial begin
reset = 1'b1;
#10;
reset = 1'b0;
end
initial begin
$dumpfile("traces/usb_ft1248_tb.vcd");
$dumpvars();
usb_pwrsav = 1'b1;
usb_miso = 1'b1;
#100;
fifo_bus.tx_write = 1'b1;
#100;
fifo_bus.tx_write = 1'b0;
#103;
usb_miso = 1'b0;
#80;
usb_scb.write_buffer_flush = 1'b1;
#1;
usb_scb.write_buffer_flush = 1'b0;
#20;
usb_miso = 1'b1;
#26;
usb_miso = 1'b0;
#4430;
usb_miso = 1'b1;
#13;
usb_miso = 1'b0;
#79;
fifo_bus.rx_read = 1'b1;
#1;
fifo_bus.rx_read = 1'b0;
#10;
fifo_bus.rx_read = 1'b1;
#1;
fifo_bus.rx_read = 1'b0;
#80;
fifo_bus.rx_read = 1'b1;
#1;
fifo_bus.rx_read = 1'b0;
#200;
usb_scb.reset_on_ack = 1'b1;
#1;
usb_scb.reset_on_ack = 1'b0;
#200;
usb_scb.reset_off_ack = 1'b1;
#1;
usb_scb.reset_off_ack = 1'b0;
#200;
usb_scb.fifo_flush = 1'b1;
#1;
usb_scb.fifo_flush = 1'b0;
#3000;
usb_scb.fifo_flush = 1'b1;
#1;
usb_scb.fifo_flush = 1'b0;
#6000;
$finish;
end
endmodule

View File

@ -0,0 +1,145 @@
module fifo_bus_fifo_mock #(
parameter int DEPTH = 1024,
parameter int FILL_RATE = 3,
parameter int DRAIN_RATE = 3
) (
input clk,
input reset,
fifo_bus.fifo fifo_bus,
input flush,
input rx_fill_enabled,
input tx_drain_enabled
);
localparam int PTR_BITS = $clog2(DEPTH);
// RX FIFO mock
logic rx_full;
logic rx_write;
logic [7:0] rx_wdata;
logic [PTR_BITS:0] rx_count;
fifo_mock #(
.DEPTH(DEPTH)
) fifo_rx (
.clk(clk),
.reset(reset),
.empty(fifo_bus.rx_empty),
.read(fifo_bus.rx_read),
.rdata(fifo_bus.rx_rdata),
.full(rx_full),
.write(rx_write),
.wdata(rx_wdata),
.count(rx_count)
);
localparam int FILL_BITS = $clog2(FILL_RATE);
logic [FILL_BITS:0] fill_counter;
logic rx_fill;
always_ff @(posedge clk) begin
rx_fill <= rx_fill_enabled;
end
generate;
if (FILL_RATE == 0) begin
always_comb begin
rx_write = rx_fill && !rx_full;
end
end else begin
always_comb begin
rx_write = rx_fill && !rx_full && (fill_counter == (FILL_BITS + 1)'(FILL_RATE));
end
always_ff @(posedge clk) begin
if (fill_counter < (FILL_BITS + 1)'(FILL_RATE)) begin
fill_counter <= fill_counter + (FILL_BITS + 1)'('d1);
end
if (reset) begin
fill_counter <= (FILL_BITS + 1)'('d0);
end else begin
if (rx_write) begin
fill_counter <= (FILL_BITS + 1)'('d0);
end
end
end
end
endgenerate
always_ff @(posedge clk) begin
if (reset) begin
rx_wdata <= 8'h01;
end else begin
if (rx_write) begin
rx_wdata <= rx_wdata + 8'h01;
end
end
end
// TX FIFO mock
logic tx_empty;
logic tx_read;
logic [7:0] tx_rdata;
logic [PTR_BITS:0] tx_count;
fifo_mock #(
.DEPTH(DEPTH)
) fifo_tx (
.clk(clk),
.reset(reset),
.empty(tx_empty),
.read(tx_read),
.rdata(tx_rdata),
.full(fifo_bus.tx_full),
.write(fifo_bus.tx_write),
.wdata(fifo_bus.tx_wdata),
.count(tx_count)
);
localparam int DRAIN_BITS = $clog2(DRAIN_RATE);
logic [DRAIN_BITS:0] drain_counter;
logic tx_drain;
always_ff @(posedge clk) begin
tx_drain <= tx_drain_enabled;
end
generate;
if (DRAIN_RATE == 0) begin
always_comb begin
tx_read = tx_drain && !tx_empty;
end
end else begin
always_comb begin
tx_read = tx_drain && !tx_empty && (drain_counter == (DRAIN_BITS + 1)'(DRAIN_RATE));
end
always_ff @(posedge clk) begin
if (drain_counter < (DRAIN_BITS + 1)'(DRAIN_RATE)) begin
drain_counter <= drain_counter + (DRAIN_BITS + 1)'('d1);
end
if (reset) begin
drain_counter <= (DRAIN_BITS + 1)'('d0);
end else begin
if (tx_read) begin
drain_counter <= (DRAIN_BITS + 1)'('d0);
end
end
end
end
endgenerate
endmodule

View File

@ -1,173 +0,0 @@
module fifo_bus_mock #(
parameter int DEPTH = 1024,
parameter int FILL_RATE = 3,
parameter int DRAIN_RATE = 3
) (
input clk,
input reset,
fifo_bus.fifo fifo_bus,
input flush,
input rx_fill_enabled,
input tx_drain_enabled
);
localparam int PTR_BITS = $clog2(DEPTH);
// RX FIFO mock
logic [7:0] rx_fifo_mem [0:(DEPTH - 1)];
logic [(PTR_BITS - 1):0] rx_fifo_rptr;
logic [(PTR_BITS - 1):0] rx_fifo_wptr;
logic [PTR_BITS:0] rx_available;
logic rx_fifo_full;
logic rx_fifo_almost_full;
logic rx_write;
logic [7:0] rx_wdata;
always_comb begin
rx_fifo_full = rx_available >= (PTR_BITS + 1)'(DEPTH);
rx_fifo_almost_full = rx_available >= (PTR_BITS + 1)'(DEPTH - 1);
fifo_bus.rx_empty = rx_available == (PTR_BITS + 1)'('d0);
fifo_bus.rx_almost_empty = rx_available <= (PTR_BITS + 1)'('d1);
end
always_ff @(posedge clk) begin
if (fifo_bus.rx_read) begin
fifo_bus.rx_rdata <= rx_fifo_mem[rx_fifo_rptr];
rx_fifo_rptr <= rx_fifo_rptr + PTR_BITS'('d1);
rx_available <= rx_available - (PTR_BITS + 1)'('d1);
end
if (rx_write) begin
rx_fifo_mem[rx_fifo_wptr] <= rx_wdata;
rx_fifo_wptr <= rx_fifo_wptr + PTR_BITS'('d1);
rx_available <= rx_available + (PTR_BITS + 1)'('d1);
end
if (fifo_bus.rx_read && rx_write) begin
rx_available <= rx_available;
end
if (reset || flush) begin
rx_available <= (PTR_BITS + 1)'('d0);
rx_fifo_rptr <= PTR_BITS'('d0);
rx_fifo_wptr <= PTR_BITS'('d0);
end
end
localparam int FILL_BITS = $clog2(FILL_RATE);
logic [FILL_BITS:0] fill_counter;
logic rx_fill;
always_ff @(posedge clk) begin
rx_fill <= rx_fill_enabled;
end
generate;
if (FILL_RATE == 0) begin
always_comb begin
rx_write = rx_fill && !rx_fifo_full;
end
end else begin
always_comb begin
rx_write = rx_fill && !rx_fifo_full && (fill_counter == (FILL_BITS + 1)'(FILL_RATE));
end
always_ff @(posedge clk) begin
if (fill_counter < (FILL_BITS + 1)'(FILL_RATE)) begin
fill_counter <= fill_counter + (FILL_BITS + 1)'('d1);
end
if (reset) begin
fill_counter <= (FILL_BITS + 1)'('d0);
end else begin
if (rx_write) begin
fill_counter <= (FILL_BITS + 1)'('d0);
end
end
end
end
endgenerate
always_ff @(posedge clk) begin
if (reset) begin
rx_wdata <= 8'h01;
end else begin
if (rx_write) begin
rx_wdata <= rx_wdata + 8'h01;
end
end
end
// TX FIFO mock
logic [7:0] tx_fifo_mem [0:(DEPTH - 1)];
logic [(PTR_BITS - 1):0] tx_fifo_rptr;
logic [(PTR_BITS - 1):0] tx_fifo_wptr;
logic [PTR_BITS:0] tx_available;
logic tx_fifo_empty;
logic tx_fifo_almost_empty;
logic tx_read;
logic [7:0] tx_rdata;
always_comb begin
tx_fifo_empty = tx_available == (PTR_BITS + 1)'('d0);
tx_fifo_almost_empty = tx_available <= (PTR_BITS + 1)'('d1);
fifo_bus.tx_full = tx_available >= (PTR_BITS + 1)'(DEPTH);
fifo_bus.tx_almost_full = tx_available >= (PTR_BITS + 1)'(DEPTH - 1);
end
always_ff @(posedge clk) begin
if (fifo_bus.tx_write) begin
tx_fifo_mem[tx_fifo_wptr] <= fifo_bus.tx_wdata;
tx_fifo_wptr <= tx_fifo_wptr + PTR_BITS'('d1);
tx_available <= tx_available + (PTR_BITS + 1)'('d1);
end
if (tx_read) begin
tx_rdata <= tx_fifo_mem[tx_fifo_rptr];
tx_fifo_rptr <= tx_fifo_rptr + PTR_BITS'('d1);
tx_available <= tx_available - (PTR_BITS + 1)'('d1);
end
if (fifo_bus.tx_write && tx_read) begin
tx_available <= tx_available;
end
if (reset || flush) begin
tx_available <= (PTR_BITS + 1)'('d0);
tx_fifo_rptr <= PTR_BITS'('d0);
tx_fifo_wptr <= PTR_BITS'('d0);
end
end
localparam int DRAIN_BITS = $clog2(DRAIN_RATE);
logic [DRAIN_BITS:0] drain_counter;
logic tx_drain;
always_ff @(posedge clk) begin
tx_drain <= tx_drain_enabled;
end
generate;
if (DRAIN_RATE == 0) begin
always_comb begin
tx_read = tx_drain && !tx_fifo_empty;
end
end else begin
always_comb begin
tx_read = tx_drain && !tx_fifo_empty && (drain_counter == (DRAIN_BITS + 1)'(DRAIN_RATE));
end
always_ff @(posedge clk) begin
if (drain_counter < (DRAIN_BITS + 1)'(DRAIN_RATE)) begin
drain_counter <= drain_counter + (DRAIN_BITS + 1)'('d1);
end
if (reset) begin
drain_counter <= (DRAIN_BITS + 1)'('d0);
end else begin
if (tx_read) begin
drain_counter <= (DRAIN_BITS + 1)'('d0);
end
end
end
end
endgenerate
endmodule

View File

@ -0,0 +1,49 @@
module fifo_mock #(
parameter int DEPTH = 1024,
localparam int PTR_BITS = $clog2(DEPTH)
) (
input clk,
input reset,
output logic empty,
input read,
output [7:0] rdata,
output logic full,
input write,
input [7:0] wdata,
output logic [PTR_BITS:0] count
);
logic [7:0] fifo_mem [0:(DEPTH - 1)];
logic [(PTR_BITS - 1):0] fifo_rptr;
logic [(PTR_BITS - 1):0] fifo_wptr;
always_comb begin
full = count >= (PTR_BITS + 1)'(DEPTH);
empty = count == (PTR_BITS + 1)'('d0);
end
always_ff @(posedge clk) begin
if (read) begin
rdata <= fifo_mem[fifo_rptr];
fifo_rptr <= fifo_rptr + PTR_BITS'('d1);
count <= count - (PTR_BITS + 1)'('d1);
end
if (write) begin
fifo_mem[fifo_wptr] <= wdata;
fifo_wptr <= fifo_wptr + PTR_BITS'('d1);
count <= count + (PTR_BITS + 1)'('d1);
end
if (read && write) begin
count <= count;
end
if (reset) begin
count <= (PTR_BITS + 1)'('d0);
fifo_rptr <= PTR_BITS'('d0);
fifo_wptr <= PTR_BITS'('d0);
end
end
endmodule

33
fw/tests/mocks/vendor/fifo_8kb.sv vendored Normal file
View File

@ -0,0 +1,33 @@
module fifo_8kb (
input clk,
input reset,
output empty,
input read,
output [7:0] rdata,
output full,
input write,
input [7:0] wdata,
output logic [10:0] count
);
fifo_mock #(
.DEPTH(1024)
) fifo_8kb (
.clk(clk),
.reset(reset),
.empty(empty),
.read(read),
.rdata(rdata),
.full(full),
.write(write),
.wdata(wdata),
.count(count)
);
endmodule