Fifo Uvm
Fifo Uvm
WITH
FIFO Design
The FIFO (First-In, First-Out) design is a memory-based circuit that stores data in the
order it is received and outputs it in the same order. It has two pointers: one for writing
data in and one for reading data out. The FIFO uses a clock to synchronize these
operations and includes signals to indicate when it is full or empty. A reset signal can
clear the memory and reset the pointers. This design helps manage data flow smoothly,
especially when transferring data between different parts of a system.
Specification Details
- data_in: 8-bit input data signal
- clock: 1-bit clock signal
Inputs - reset: 1-bit reset signal (active high)
- wn: 1-bit write enable signal
- rn: 1-bit read enable signal
- data_out: 8-bit output data signal
Outputs - full: 1-bit flag indicating FIFO is full
- empty: 1-bit flag indicating FIFO is empty
- wptr: 3-bit write pointer
Internal
- rptr: 3-bit read pointer
Signals
- memory: 8-entry array of 8-bit registers (FIFO storage)
- Reset: On a high reset signal, all entries in the FIFO memory are
cleared, wptr and rptr are reset to 0, and data_out is set to 0.
- Write Operation: When wn is high and full is low, data_in is
written into the FIFO at the position indicated by wptr. The wptr is
then incremented.
- Read Operation: When rn is high and empty is low, data from the
Behavior FIFO at the position indicated by rptr is output through data_out.
The rptr is then incremented.
- Full Condition: The FIFO is considered full when wptr[2:1] ==
rptr[2:1] and wptr[0] != rptr[0]. When full, no further write
operations are allowed.
- Empty Condition: The FIFO is considered empty when wptr ==
rptr. When empty, no further read operations are allowed.
Synchronous with the clock signal. Operations are triggered on the
Clocking
positive edge of clock.
Memory 8 entries (indexed by 3-bit pointers)
Depth
Data Width 8 bits per entry
- Buffering: Temporarily stores data to handle timing differences
between producer and consumer modules.
Use Cases
- Queue Management: Manages data flow in a first-in, first-out
manner.
Testbench Architecture
Design.V
module FIFO (
output reg [7:0] data_out,
output full, empty,
input [7:0] data_in,
input clock, reset, wn, rn
);
reg [2:0] wptr, rptr;
reg [7:0] memory [7:0];
// Read operation
if (rn && !empty) begin
data_out <= memory[rptr];
rptr <= rptr + 1;
end
end
end
endmodule
Interface
output wn;
output rn;
output data_in;
input full;
input empty;
input data_out;
endclocking
input wn;
input rn;
input data_in;
input full;
input empty;
input data_out;
endclocking
endinterface
Sequence Item
`uvm_object_utils_begin(seq_item)
`uvm_field_int(data_in,UVM_ALL_ON)
`uvm_field_int(wn,UVM_ALL_ON)
`uvm_field_int(rn,UVM_ALL_ON)
`uvm_field_int(full,UVM_ALL_ON)
`uvm_field_int(data_out,UVM_ALL_ON)
`uvm_object_utils_end
endclass
Sequence
endclass
Sequencer
endclass
Driver
forever begin
seq_item req;
seq_item_port.get_next_item(req);
if (req.wn == 1)
main_write(req.data_in);
else if (req.rn == 1)
main_read();
seq_item_port.item_done();
end
endtask
endclass
Monitor
seq_item mon_item;
forever begin
@(posedge vif.clock);
item_collect_port.write(mon_item);
end
end
endtask
endclass
Agent
sequencer seqr;
driver drv;
monitor mon;
if(get_is_active==UVM_ACTIVE)
begin
drv=driver::type_id::create("drv",this);
seqr=sequencer::type_id::create("seqr",this);
end
mon=monitor::type_id::create("mon",this);
endfunction
if(get_is_active == UVM_ACTIVE)
begin
drv.seq_item_port.connect(seqr.seq_item_export);
end
endfunction
endclass
Environment
agent agt;
scoreboard sb;
agt=agent::type_id::create("env",this);
sb=scoreboard::type_id::create("sb",this);
endfunction
agt.mon.item_collect_port.connect(sb.item_collect_export);
endfunction
endclass
Scoreboard
int expected_data_queue[$];
// Declare the covergroup and the sequence item used for coverage
seq_item cov_data_pkt;
covergroup fifo_coverage;
endgroup : fifo_coverage
$display("-------------------------------------------------");
$display("Overall Coverage: %0.2f%%",
$get_coverage());
$display("Coverage of covergroup 'FIFO_coverage': %0.2f%%",
fifo_coverage.get_coverage());
$display("Coverage of coverpoint 'DATA_IN' = %0f",
fifo_coverage.DATA_IN.get_coverage());
$display("Coverage of coverpoint 'WRITE_CMD' = %0f",
fifo_coverage.WRITE_CMD.get_coverage());
$display("Coverage of coverpoint 'READ_CMD' = %0f",
fifo_coverage.READ_CMD.get_coverage());
$display("Coverage of coverpoint 'EMPTY_CMD' = %0f",
fifo_coverage.EMPTY_CMD.get_coverage());
$display("Coverage of coverpoint 'FULL_CMD' = %0f",
fifo_coverage.FULL_CMD.get_coverage());
$display("-------------------------------------------------");
$display("-------------------------------------------");
endfunction
endclass
Test
env env_o;
base_seq bseq;
env_o=env::type_id::create("env_o",this);
bseq=base_seq::type_id::create("bseq",this);
endfunction
endclass
Testbench Top
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "interface.sv"
`include "package.sv"
module tb_top;
bit clock;
bit reset;
always #5 clock=~clock;
initial
begin
clock=0;
reset=1;
#10 reset=0;
end
fifo_if vif(clock,reset);
FIFO DUT (
.data_out(vif.data_out),
.full(vif.full),
.empty(vif.empty),
.clock(vif.clock),
.reset(vif.reset),
.wn(vif.wn),
.rn(vif.rn),
.data_in(vif.data_in)
);
initial
begin
uvm_config_db #(virtual fifo_if)::set(uvm_root::get(),"*","vif",vif);
$dumpvars;
end
initial
begin
run_test("base_test");
end
endmodule
Package
import uvm_pkg::*;
`include "seq_item.sv"
`include "base_seq.sv"
`include "sequencer.sv"
`include "driver.sv"
`include "monitor.sv"
`include "scoreboard.sv"
`include "agent.sv"
`include "env.sv"
`include "base_test.sv"