diff --git a/fw/project/lcmxo2/sc64.ldf b/fw/project/lcmxo2/sc64.ldf index 20dcae1..5d2cc62 100644 --- a/fw/project/lcmxo2/sc64.ldf +++ b/fw/project/lcmxo2/sc64.ldf @@ -15,6 +15,9 @@ + + + diff --git a/fw/project/lcmxo2/sc64.lpf b/fw/project/lcmxo2/sc64.lpf index 2d61e26..3fd38a2 100644 --- a/fw/project/lcmxo2/sc64.lpf +++ b/fw/project/lcmxo2/sc64.lpf @@ -214,7 +214,7 @@ LOCATE COMP "usb_miso" SITE "10" ; LOCATE COMP "usb_pwrsav" SITE "2" ; SYSCONFIG SDM_PORT=DISABLE I2C_PORT=ENABLE ; 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 "n64_irq" ; BLOCK PATH FROM PORT "usb_pwrsav" ; diff --git a/fw/rtl/fifo/fifo_bus.sv b/fw/rtl/fifo/fifo_bus.sv index 80ca607..9d3c17f 100644 --- a/fw/rtl/fifo/fifo_bus.sv +++ b/fw/rtl/fifo/fifo_bus.sv @@ -1,35 +1,29 @@ interface fifo_bus (); logic rx_empty; - logic rx_almost_empty; logic rx_read; logic [7:0] rx_rdata; logic tx_full; - logic tx_almost_full; logic tx_write; logic [7:0] tx_wdata; modport controller ( input rx_empty, - input rx_almost_empty, output rx_read, input rx_rdata, input tx_full, - input tx_almost_full, output tx_write, output tx_wdata ); modport fifo ( output rx_empty, - output rx_almost_empty, input rx_read, output rx_rdata, output tx_full, - output tx_almost_full, input tx_write, input tx_wdata ); diff --git a/fw/rtl/fifo/fifo_junction.sv b/fw/rtl/fifo/fifo_junction.sv index cd3ffdc..459c218 100644 --- a/fw/rtl/fifo/fifo_junction.sv +++ b/fw/rtl/fifo/fifo_junction.sv @@ -11,16 +11,12 @@ module fifo_junction ( 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_almost_empty = dev_bus.rx_almost_empty; cfg_bus.rx_rdata = dev_bus.rx_rdata; 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_almost_empty = dev_bus.rx_almost_empty; dma_bus.rx_rdata = dev_bus.rx_rdata; dma_bus.tx_full = dev_bus.tx_full; - dma_bus.tx_almost_full = dev_bus.tx_almost_full; end endmodule diff --git a/fw/rtl/memory/memory_sdram.sv b/fw/rtl/memory/memory_sdram.sv index f112241..0d4179b 100644 --- a/fw/rtl/memory/memory_sdram.sv +++ b/fw/rtl/memory/memory_sdram.sv @@ -22,20 +22,22 @@ module memory_sdram ( // in nanoseconds 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_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_RP = 15.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 [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 [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 [4:0] C_RP = 5'(int'($ceil(T_RP / T_CLK))); const bit [4:0] INIT_PRECHARGE = 5'd0; const bit [4:0] INIT_REFRESH_1 = INIT_PRECHARGE + C_RP; @@ -139,8 +141,10 @@ module memory_sdram ( logic [13:0] refresh_counter; logic [4:0] wait_counter; + logic [2:0] precharge_counter; logic powerup_done; logic pending_refresh; + logic precharge_valid; always_ff @(posedge clk) begin refresh_counter <= refresh_counter + 1'd1; @@ -170,6 +174,17 @@ module memory_sdram ( if (state != next_state) begin wait_counter <= 5'd0; 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 logic [(CAS_LATENCY):0] read_cmd_ack_delay; @@ -228,14 +243,14 @@ module memory_sdram ( end S_ACTIVE: begin - if (pending_refresh) begin + if (pending_refresh && precharge_valid) begin next_state = S_PRECHARGE; sdram_next_cmd = CMD_PRE; end else if (mem_bus.request) begin if (request_in_current_active_bank_row) begin next_state = S_BUSY; sdram_next_cmd = mem_bus.write ? CMD_WRITE : CMD_READ; - end else begin + end else if (precharge_valid) begin next_state = S_PRECHARGE; sdram_next_cmd = CMD_PRE; end diff --git a/fw/rtl/sd/sd_dat.sv b/fw/rtl/sd/sd_dat.sv index 419efa8..00c88c4 100644 --- a/fw/rtl/sd/sd_dat.sv +++ b/fw/rtl/sd/sd_dat.sv @@ -36,12 +36,10 @@ module sd_dat ( // FIFO logic rx_full; - logic rx_almost_full; logic rx_write; logic [7:0] rx_wdata; logic tx_empty; - logic tx_almost_empty; logic tx_read; logic [7:0] tx_rdata; @@ -50,12 +48,10 @@ module sd_dat ( .reset(reset || sd_scb.dat_fifo_flush), .empty(fifo_bus.rx_empty), - .almost_empty(fifo_bus.rx_almost_empty), .read(fifo_bus.rx_read), .rdata(fifo_bus.rx_rdata), .full(rx_full), - .almost_full(rx_almost_full), .write(rx_write), .wdata(rx_wdata), @@ -67,12 +63,10 @@ module sd_dat ( .reset(reset || sd_scb.dat_fifo_flush), .empty(tx_empty), - .almost_empty(tx_almost_empty), .read(tx_read), .rdata(tx_rdata), .full(fifo_bus.tx_full), - .almost_full(fifo_bus.tx_almost_full), .write(fifo_bus.tx_write), .wdata(fifo_bus.tx_wdata), diff --git a/fw/rtl/usb/usb_ft1248.sv b/fw/rtl/usb/usb_ft1248.sv index d60d8ad..0a31308 100644 --- a/fw/rtl/usb/usb_ft1248.sv +++ b/fw/rtl/usb/usb_ft1248.sv @@ -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 ( input clk, input reset, @@ -53,12 +14,10 @@ module usb_ft1248 ( ); logic rx_full; - logic rx_almost_full; - logic rx_write; + logic rx_write_delayed; logic [7:0] rx_wdata; logic tx_empty; - logic tx_almost_empty; logic tx_read; logic [7:0] tx_rdata; @@ -69,13 +28,11 @@ module usb_ft1248 ( .reset(reset || fifo_flush), .empty(fifo_bus.rx_empty), - .almost_empty(fifo_bus.rx_almost_empty), .read(fifo_bus.rx_read), .rdata(fifo_bus.rx_rdata), .full(rx_full), - .almost_full(rx_almost_full), - .write(rx_write), + .write(rx_write_delayed), .wdata(rx_wdata), .count(usb_scb.rx_count) @@ -86,12 +43,10 @@ module usb_ft1248 ( .reset(reset || fifo_flush), .empty(tx_empty), - .almost_empty(tx_almost_empty), .read(tx_read), .rdata(tx_rdata), .full(fifo_bus.tx_full), - .almost_full(fifo_bus.tx_almost_full), .write(fifo_bus.tx_write), .wdata(fifo_bus.tx_wdata), @@ -145,6 +100,8 @@ module usb_ft1248 ( e_cmd cmd; e_cmd next_cmd; logic [3:0] phase; + logic rx_write; + logic last_rx_failed; logic last_tx_failed; logic reset_reply; logic [4:0] modem_status_counter; @@ -158,6 +115,8 @@ module usb_ft1248 ( usb_scb.pwrsav <= !ft_pwrsav; fifo_flush <= 1'b0; + rx_write_delayed <= rx_write; + phase <= {phase[2:0], phase[3]}; if (state == STATE_IDLE) begin phase <= 4'b0100; @@ -166,6 +125,7 @@ module usb_ft1248 ( if (reset) begin usb_scb.fifo_flush_busy <= 1'b0; usb_scb.reset_state <= 1'b0; + last_rx_failed <= 1'b0; last_tx_failed <= 1'b0; reset_reply <= 1'b0; modem_status_counter <= 5'd0; @@ -195,9 +155,19 @@ module usb_ft1248 ( if (usb_scb.fifo_flush_busy) begin usb_scb.fifo_flush_busy <= 1'b0; 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 + 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 last_tx_failed <= ft_miso; end @@ -262,8 +232,6 @@ module usb_ft1248 ( rx_write = 1'b0; tx_read = 1'b0; - rx_wdata = ft_miosi_in; - if (!ft_miso && phase[3]) begin case (state) STATE_STATUS: begin @@ -273,13 +241,15 @@ module usb_ft1248 ( end STATE_DATA: begin - if (cmd == CMD_READ) begin + if (cmd == CMD_READ && !rx_full) begin rx_write = 1'b1; end if (cmd == CMD_WRITE && !tx_empty) begin tx_read = 1'b1; end end + + default: begin end endcase end end @@ -340,7 +310,7 @@ module usb_ft1248 ( if (ft_miso) begin next_state = STATE_DESELECT; end else if (cmd == CMD_READ) begin - if (rx_almost_full) begin + if (rx_full) begin next_state = STATE_DESELECT; end end else if (cmd == CMD_WRITE) begin diff --git a/fw/rtl/usb/usb_scb.sv b/fw/rtl/usb/usb_scb.sv new file mode 100644 index 0000000..b2a322d --- /dev/null +++ b/fw/rtl/usb/usb_scb.sv @@ -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 diff --git a/fw/rtl/vendor/lcmxo2/fifo_8kb.sv b/fw/rtl/vendor/lcmxo2/fifo_8kb.sv index db02ad2..05fb8b3 100644 --- a/fw/rtl/vendor/lcmxo2/fifo_8kb.sv +++ b/fw/rtl/vendor/lcmxo2/fifo_8kb.sv @@ -3,18 +3,19 @@ module fifo_8kb ( input reset, output empty, - output almost_empty, input read, output [7:0] rdata, output full, - output almost_full, input write, input [7:0] wdata, - + output logic [10:0] count ); + logic almost_empty; + logic almost_full; + fifo_8kb_lattice_generated fifo_8kb_lattice_generated_inst ( .Data(wdata), .WrClock(clk), @@ -25,7 +26,7 @@ module fifo_8kb ( .RPReset(reset), .Q(rdata), .Empty(empty), - .Full(full), + .Full(full), .AlmostEmpty(almost_empty), .AlmostFull(almost_full) ); diff --git a/fw/tests/Makefile b/fw/tests/Makefile index 0c17476..42e11a1 100644 --- a/fw/tests/Makefile +++ b/fw/tests/Makefile @@ -1,4 +1,5 @@ RTL_DIR = ../rtl +BENCHES_DIR = benches MOCKS_DIR = mocks BUILD_DIR = build SRC_DIRS = \ @@ -11,10 +12,11 @@ SRC_DIRS = \ $(RTL_DIR)/usb \ $(RTL_DIR)/vendor \ $(RTL_DIR) \ + $(MOCKS_DIR)/vendor \ $(MOCKS_DIR) 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))) VERILATOR_FLAGS = --binary --trace --timescale 10ns/1ns -j --quiet $(INC_DIRS) diff --git a/fw/tests/memory/memory_dma_tb.sv b/fw/tests/benches/memory_dma_tb.sv similarity index 96% rename from fw/tests/memory/memory_dma_tb.sv rename to fw/tests/benches/memory_dma_tb.sv index 359c54b..aa08d5a 100644 --- a/fw/tests/memory/memory_dma_tb.sv +++ b/fw/tests/benches/memory_dma_tb.sv @@ -41,11 +41,11 @@ module memory_dma_tb; .transfer_length(transfer_length) ); - fifo_bus_mock #( + fifo_bus_fifo_mock #( .DEPTH(16), .FILL_RATE(16), .DRAIN_RATE(16) - ) fifo_bus_mock ( + ) fifo_bus_fifo_mock ( .clk(clk), .reset(reset), @@ -103,7 +103,7 @@ module memory_dma_tb; #1; stop = 1'b0; - #99; + #165; start = 1'b1; direction = 1'b1; diff --git a/fw/tests/benches/usb_ft1248_tb.sv b/fw/tests/benches/usb_ft1248_tb.sv new file mode 100644 index 0000000..8c62dd5 --- /dev/null +++ b/fw/tests/benches/usb_ft1248_tb.sv @@ -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 diff --git a/fw/tests/mocks/fifo_bus_fifo_mock.sv b/fw/tests/mocks/fifo_bus_fifo_mock.sv new file mode 100644 index 0000000..2fc57de --- /dev/null +++ b/fw/tests/mocks/fifo_bus_fifo_mock.sv @@ -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 diff --git a/fw/tests/mocks/fifo_bus_mock.sv b/fw/tests/mocks/fifo_bus_mock.sv deleted file mode 100644 index bfa2a1c..0000000 --- a/fw/tests/mocks/fifo_bus_mock.sv +++ /dev/null @@ -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 diff --git a/fw/tests/mocks/fifo_mock.sv b/fw/tests/mocks/fifo_mock.sv new file mode 100644 index 0000000..acf9065 --- /dev/null +++ b/fw/tests/mocks/fifo_mock.sv @@ -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 diff --git a/fw/tests/mocks/vendor/fifo_8kb.sv b/fw/tests/mocks/vendor/fifo_8kb.sv new file mode 100644 index 0000000..f20105b --- /dev/null +++ b/fw/tests/mocks/vendor/fifo_8kb.sv @@ -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