Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replay FIFO #21

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions FIFO/Replay_FIFO/FIFO_TB.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// A testbench for a FIFO
`timescale 1ns/10ps

module FIFO_TB;

localparam CLK_PERIOD = 10;
localparam FIFO_DEPTH_LG2 = 4;
localparam DATA_WIDTH = 32;

localparam TEST_DATA_CNT = 128;
localparam TEST_TIMEOUT = 100000;


//----------------------------------------------------------
// Clock and reset generation
//----------------------------------------------------------
logic clk;
logic rst_n;

initial begin
clk = 1'b0;
forever
#(CLK_PERIOD/2) clk = ~clk;
end

initial begin
rst_n = 1'b0;
repeat (3) @(posedge clk); // wait for 3 clocks
rst_n = 1'b1;
end

//----------------------------------------------------------
// Design-Under-Test (DUT)
//----------------------------------------------------------
wire full, empty;
logic wren, rden;
logic [DATA_WIDTH-1:0] wdata, rdata;
logic ACK, NAK;

FIFO
#(
.DEPTH_LG2 (FIFO_DEPTH_LG2),
.DATA_WIDTH (DATA_WIDTH)
)
dut
(
.clk (clk),
.rst_n (rst_n),

.full_o (full),
.wren_i (wren),
.wdata_i (wdata),

.empty_o (empty),
.rden_i (rden),
.rdata_o (rdata),

.ACK (ACK),
.NAK (NAK)
);

//----------------------------------------------------------
// Driver, Monitor, and Scoreboard
//----------------------------------------------------------

// A scoreboard to hold expected data
mailbox data_sb = new(); // unlimited size

// Push driver
initial begin
wren = 1'b0;
wdata = 'hX;
@(posedge rst_n); // wait for the reset release

for (int i=0; i<TEST_DATA_CNT; i=i+1) begin
@(posedge clk);
#1
wren = 1'b0;
if (~full) begin
if (($random()%3)==0) begin // push with 33% probability
wren = 1'b1;
wdata = $urandom();
data_sb.put(wdata);
$display($time, "ns, pushing %x", wdata);
end
end
end
wren = 1'b0;
end

// Pop driver/monitor
initial begin
rden = 1'b0;

@(posedge rst_n); // wait for the reset release

for (int i=0; i<TEST_DATA_CNT; i=i+1) begin
@(posedge clk);
#1
rden = 1'b0;
ACK = 1'b0;
NAK = 1'b0;

if (~empty) begin
// step 1: check

// peek the expected data from the scoreboard
int peak_result;
logic [DATA_WIDTH-1:0] expected_data;
logic [DATA_WIDTH-1:0] expected_data_test;
peak_result = data_sb.try_peek(expected_data);

if (peak_result==0) begin
$fatal($time, "ns, the scoreboard is empty: %d", peak_result);
end

// compare against the rdata
if (expected_data===rdata) begin // "===" instead of "==" to compare against Xs
$display($time, "ns, peeking matching data: %x", rdata);
end
else begin
$fatal($time, "ns, data mismatch: %x (exp) %x (DUT)", expected_data, rdata);
end

// step 2: pop the entry
if (($random()%3)==0) begin // pop with 33% probability
// pop from the DUT
rden = 1'b1;
// pop from the scoreboard -> discard

#1
if (($random()%2)==0) begin // ACK with 50% probability
ACK = 1'b1;
NAK = 1'b0;
data_sb.get(expected_data);
$display($time, "ns, popping matching data: %x", rdata);
end else begin // NAK with 50% probability
ACK = 1'b0;
NAK = 1'b1;
$display($time, "ns, NAK occurs and replays: %x", rdata);
end
end
end
end
rden = 1'b0;

repeat(10) @(posedge clk);
$finish;
end

// Time-out
initial begin
#TEST_TIMEOUT
$display("Simulation timed out!");
$fatal("Simulation timed out");
end

endmodule
108 changes: 108 additions & 0 deletions FIFO/Replay_FIFO/ReplayFIFO.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
module FIFO #(
parameter DEPTH_LG2 = 4,
parameter DATA_WIDTH = 32,
parameter RST_MEM = 0
)
(
input wire clk,
input wire rst_n,

output wire full_o,
input wire wren_i,
input wire [DATA_WIDTH-1:0] wdata_i,

input wire ACK, // Acknowledge
input wire NAK, // Negative Acknowledge

output wire empty_o,
input wire rden_i,
output wire [DATA_WIDTH-1:0] rdata_o
);

localparam FIFO_DEPTH = (1<<DEPTH_LG2);

reg [DATA_WIDTH-1:0] mem[FIFO_DEPTH];

reg full, full_n,
empty, empty_n;
reg [DEPTH_LG2:0] wrptr, wrptr_n, // write pointer
rdptr, rdptr_n, // read pointer
rdptr_re; // read pointer buffer to replay

always_ff @(posedge clk)
if (!rst_n & RST_MEM) begin
for (int i = 0; i < FIFO_DEPTH; i++) begin
mem[i] <= {DATA_WIDTH{1'b0}};
end
end
else begin
if (wren_i) begin
mem[wrptr[DEPTH_LG2-1:0]] <= wdata_i; // write data
end
end

always_ff @(posedge clk)
if (!rst_n) begin
full <= 1'b0;
empty <= 1'b1; // empty after as reset

wrptr <= {(DEPTH_LG2+1){1'b0}};
rdptr <= {(DEPTH_LG2+1){1'b0}};
rdptr_re <= {(DEPTH_LG2+1){1'b0}};
end
else begin
full <= full_n;
empty <= empty_n;
wrptr <= wrptr_n;

if (NAK) begin
rdptr <= rdptr_re;
end
else begin
rdptr <= rdptr_n;
end

if (ACK) begin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Receive an ack sequence number from the input, and update the rdptr_re with the number.

rdptr_re <= rdptr_n;
end
end

always_comb begin
wrptr_n = wrptr;
rdptr_n = rdptr;

if (wren_i) begin
wrptr_n = wrptr + 'd1;
end

if (rden_i) begin
rdptr_n = rdptr + 'd1;
end

empty_n = (wrptr_n == rdptr_n);
full_n = (wrptr_n[DEPTH_LG2] != rdptr_n[DEPTH_LG2])
& (wrptr_n[DEPTH_LG2-1:0] == rdptr_n[DEPTH_LG2-1:0]);
end

// synthesis translate_off
always @(posedge clk) begin
if (full_o & wren_i) begin
$display("FIFO overflow");
@(posedge clk);
$finish;
end
end
always @(posedge clk) begin
if (empty_o & rden_i) begin
$display("FIFO underflow");
@(posedge clk);
$finish;
end
end
// synthesis translate_on

assign full_o = full;
assign empty_o = empty;
assign rdata_o = mem[rdptr[DEPTH_LG2-1:0]];

endmodule
2 changes: 2 additions & 0 deletions FIFO/Replay_FIFO/filelist.f
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FIFO_TB.sv
ReplayFIFO.sv
1 change: 1 addition & 0 deletions FIFO/Replay_FIFO/run.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vcs -full64 -kdb -debug_access+all -LDFLAGS -Wl,--no-as-needed -sverilog -f filelist.f