module FIFO(input clk, rst, wr, rd,
input [7:0] din, output reg [7:0] dout,
output empty, full);
// Pointers for write and read operations
reg [3:0] wptr = 0, rptr = 0;
// Counter for tracking the number of elements in the FIFO
reg [4:0] cnt = 0;
// Memory array to store data
reg [7:0] mem [15:0];
always @(posedge clk)
begin
if (rst == 1'b1)
begin
// Reset the pointers and counter when the reset signal is asserted
wptr <= 0;
rptr <= 0;
cnt <= 0;
end
else if (wr && !full)
begin
// Write data to the FIFO if it's not full
mem[wptr] <= din;
wptr <= wptr + 1;
cnt <= cnt + 1;
end
else if (rd && !empty)
begin
// Read data from the FIFO if it's not empty
dout <= mem[rptr];
rptr <= rptr + 1;
cnt <= cnt - 1;
end
end
// Determine if the FIFO is empty or full
assign empty = (cnt == 0) ? 1'b1 : 1'b0;
assign full = (cnt == 16) ? 1'b1 : 1'b0;
endmodule
//////////////////////////////////////
// Define an interface for the FIFO
interface fifo_if;
logic clock, rd, wr; // Clock, read, and write signals
logic full, empty; // Flags indicating FIFO status
logic [7:0] data_in; // Data input
logic [7:0] data_out; // Data output
logic rst; // Reset signal
endinterface
class transaction;
rand bit oper; // Randomized bit for operation control (1 or 0)
bit rd, wr; // Read and write control bits
bit [7:0] data_in; // 8-bit data input
bit full, empty; // Flags for full and empty status
bit [7:0] data_out; // 8-bit data output
constraint oper_ctrl {
oper dist {1 :/ 50 , 0 :/ 50}; // Constraint to randomize 'oper' with 50%
probability of 1 and 50% probability of 0
}
endclass
///////////////////////////////////////////////////
class generator;
transaction tr; // Transaction object to generate and send
mailbox #(transaction) mbx; // Mailbox for communication
int count = 0; // Number of transactions to generate
int i = 0; // Iteration counter
event next; // Event to signal when to send the next transaction
event done; // Event to convey completion of requested number of
transactions
function new(mailbox #(transaction) mbx);
[Link] = mbx;
tr = new();
endfunction;
task run();
repeat (count) begin
assert ([Link]) else $error("Randomization failed");
i++;
[Link](tr);
$display("[GEN] : Oper : %0d iteration : %0d", [Link], i);
@(next);
end
-> done;
endtask
endclass
////////////////////////////////////////////
class driver;
virtual fifo_if fif; // Virtual interface to the FIFO
mailbox #(transaction) mbx; // Mailbox for communication
transaction datac; // Transaction object for communication
function new(mailbox #(transaction) mbx);
[Link] = mbx;
endfunction;
// Reset the DUT
task reset();
[Link] <= 1'b1;
[Link] <= 1'b0;
[Link] <= 1'b0;
fif.data_in <= 0;
repeat (5) @(posedge [Link]);
[Link] <= 1'b0;
$display("[DRV] : DUT Reset Done");
$display("------------------------------------------");
endtask
// Write data to the FIFO
task write();
@(posedge [Link]);
[Link] <= 1'b0;
[Link] <= 1'b0;
[Link] <= 1'b1;
fif.data_in <= $urandom_range(1, 10);
@(posedge [Link]);
[Link] <= 1'b0;
$display("[DRV] : DATA WRITE data : %0d", fif.data_in);
@(posedge [Link]);
endtask
// Read data from the FIFO
task read();
@(posedge [Link]);
[Link] <= 1'b0;
[Link] <= 1'b1;
[Link] <= 1'b0;
@(posedge [Link]);
[Link] <= 1'b0;
$display("[DRV] : DATA READ");
@(posedge [Link]);
endtask
// Apply random stimulus to the DUT
task run();
forever begin
[Link](datac);
if ([Link] == 1'b1)
write();
else
read();
end
endtask
endclass
///////////////////////////////////////////////////////
class monitor;
virtual fifo_if fif; // Virtual interface to the FIFO
mailbox #(transaction) mbx; // Mailbox for communication
transaction tr; // Transaction object for monitoring
function new(mailbox #(transaction) mbx);
[Link] = mbx;
endfunction;
task run();
tr = new();
forever begin
repeat (2) @(posedge [Link]);
[Link] = [Link];
[Link] = [Link];
tr.data_in = fif.data_in;
[Link] = [Link];
[Link] = [Link];
@(posedge [Link]);
tr.data_out = fif.data_out;
[Link](tr);
$display("[MON] : Wr:%0d rd:%0d din:%0d dout:%0d full:%0d empty:%0d", [Link],
[Link], tr.data_in, tr.data_out, [Link], [Link]);
end
endtask
endclass
/////////////////////////////////////////////////////
class scoreboard;
mailbox #(transaction) mbx; // Mailbox for communication
transaction tr; // Transaction object for monitoring
event next;
bit [7:0] din[$]; // Array to store written data
bit [7:0] temp; // Temporary data storage
int err = 0; // Error count
function new(mailbox #(transaction) mbx);
[Link] = mbx;
endfunction;
task run();
forever begin
[Link](tr);
$display("[SCO] : Wr:%0d rd:%0d din:%0d dout:%0d full:%0d empty:%0d", [Link],
[Link], tr.data_in, tr.data_out, [Link], [Link]);
if ([Link] == 1'b1) begin
if ([Link] == 1'b0) begin
din.push_front(tr.data_in);
$display("[SCO] : DATA STORED IN QUEUE :%0d", tr.data_in);
end
else begin
$display("[SCO] : FIFO is full");
end
$display("--------------------------------------");
end
if ([Link] == 1'b1) begin
if ([Link] == 1'b0) begin
temp = din.pop_back();
if (tr.data_out == temp)
$display("[SCO] : DATA MATCH");
else begin
$error("[SCO] : DATA MISMATCH");
err++;
end
end
else begin
$display("[SCO] : FIFO IS EMPTY");
end
$display("--------------------------------------");
end
-> next;
end
endtask
endclass
///////////////////////////////////////////////////////
class environment;
generator gen;
driver drv;
monitor mon;
scoreboard sco;
mailbox #(transaction) gdmbx; // Generator + Driver mailbox
mailbox #(transaction) msmbx; // Monitor + Scoreboard mailbox
event nextgs;
virtual fifo_if fif;
function new(virtual fifo_if fif);
gdmbx = new();
gen = new(gdmbx);
drv = new(gdmbx);
msmbx = new();
mon = new(msmbx);
sco = new(msmbx);
[Link] = fif;
[Link] = [Link];
[Link] = [Link];
[Link] = nextgs;
[Link] = nextgs;
endfunction
task pre_test();
[Link]();
endtask
task test();
fork
[Link]();
[Link]();
[Link]();
[Link]();
join_any
endtask
task post_test();
wait([Link]);
$display("---------------------------------------------");
$display("Error Count :%0d", [Link]);
$display("---------------------------------------------");
$finish();
endtask
task run();
pre_test();
test();
post_test();
endtask
endclass
///////////////////////////////////////////////////////
module tb;
fifo_if fif();
FIFO dut ([Link], [Link], [Link], [Link], fif.data_in, fif.data_out,
[Link], [Link]);
initial begin
[Link] <= 0;
end
always #10 [Link] <= ~[Link];
environment env;
initial begin
env = new(fif);
[Link] = 10;
[Link]();
end
initial begin
$dumpfile("[Link]");
$dumpvars;
end
endmodule