-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
548599f
commit c566669
Showing
11 changed files
with
629 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// Author: Kareem Waseem | ||
// Course: Digital Verification using SV & UVM | ||
// | ||
// Description: FIFO Design | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
module FIFO(data_in, wr_en, rd_en, clk, rst_n, full, empty, almostfull, almostempty, wr_ack, overflow, underflow, data_out); | ||
parameter FIFO_WIDTH = 16; | ||
parameter FIFO_DEPTH = 8; | ||
input [FIFO_WIDTH-1:0] data_in; | ||
input clk, rst_n, wr_en, rd_en; | ||
output reg [FIFO_WIDTH-1:0] data_out; | ||
output reg wr_ack, overflow; | ||
output full, empty, almostfull, almostempty, underflow; | ||
|
||
localparam max_fifo_addr = $clog2(FIFO_DEPTH); | ||
|
||
reg [FIFO_WIDTH-1:0] mem [FIFO_DEPTH-1:0]; | ||
|
||
reg [max_fifo_addr-1:0] wr_ptr, rd_ptr; | ||
reg [max_fifo_addr:0] count; | ||
|
||
always @(posedge clk or negedge rst_n) begin | ||
if (!rst_n) begin | ||
wr_ptr <= 0; | ||
end | ||
else if (wr_en && count < FIFO_DEPTH) begin | ||
mem[wr_ptr] <= data_in; | ||
wr_ack <= 1; | ||
wr_ptr <= wr_ptr + 1; | ||
end | ||
else begin | ||
wr_ack <= 0; | ||
if (full & wr_en) | ||
overflow <= 1; | ||
else | ||
overflow <= 0; | ||
end | ||
end | ||
|
||
always @(posedge clk or negedge rst_n) begin | ||
if (!rst_n) begin | ||
rd_ptr <= 0; | ||
end | ||
else if (rd_en && count != 0) begin | ||
data_out <= mem[rd_ptr]; | ||
rd_ptr <= rd_ptr + 1; | ||
end | ||
end | ||
|
||
always @(posedge clk or negedge rst_n) begin | ||
if (!rst_n) begin | ||
count <= 0; | ||
end | ||
else begin | ||
if ( ({wr_en, rd_en} == 2'b10) && !full) | ||
count <= count + 1; | ||
else if ( ({wr_en, rd_en} == 2'b01) && !empty) | ||
count <= count - 1; | ||
end | ||
end | ||
|
||
assign full = (count == FIFO_DEPTH)? 1 : 0; | ||
assign empty = (count == 0)? 1 : 0; | ||
assign underflow = (empty && rd_en)? 1 : 0; | ||
assign almostfull = (count == FIFO_DEPTH-2)? 1 : 0; | ||
assign almostempty = (count == 1)? 1 : 0; | ||
|
||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
//////////////////////////////////////////////////////////////////////////////// | ||
// Author: Kareem Waseem | ||
// Course: Digital Verification using SV & UVM | ||
// | ||
// Description: FIFO Design | ||
// | ||
//////////////////////////////////////////////////////////////////////////////// | ||
module FIFO(fifo_if.DUT fifoif); | ||
parameter FIFO_WIDTH = 16; | ||
parameter FIFO_DEPTH = 8; | ||
logic clk; | ||
logic [FIFO_WIDTH-1:0] data_in; | ||
logic rst_n, wr_en, rd_en; | ||
logic [FIFO_WIDTH-1:0] data_out; | ||
logic wr_ack, overflow; | ||
logic full, empty, almostfull, almostempty, underflow; | ||
|
||
// assigning signals to be interfaced | ||
// inputs | ||
assign clk = fifoif.clk; | ||
assign data_in = fifoif.data_in; | ||
assign rst_n = fifoif.rst_n; | ||
assign wr_en = fifoif.wr_en; | ||
assign rd_en = fifoif.rd_en; | ||
// outputs | ||
assign fifoif.data_out = data_out; | ||
assign fifoif.wr_ack = wr_ack; | ||
assign fifoif.overflow = overflow; | ||
assign fifoif.full = full; | ||
assign fifoif.empty = empty; | ||
assign fifoif.almostfull = almostfull; | ||
assign fifoif.almostempty = almostempty; | ||
assign fifoif.underflow = underflow; | ||
|
||
|
||
|
||
localparam max_fifo_addr = $clog2(FIFO_DEPTH); | ||
|
||
reg [FIFO_WIDTH-1:0] mem [FIFO_DEPTH-1:0]; | ||
|
||
reg [max_fifo_addr-1:0] wr_ptr, rd_ptr; | ||
reg [max_fifo_addr:0] count; | ||
|
||
// properties | ||
// immediate signals | ||
always_comb begin | ||
if(!rst_n) begin | ||
`ifdef SIM | ||
count_aa: assert final(count == 0); | ||
wr_ptr_aa: assert final(wr_ptr == 0); | ||
rd_ptr_aa: assert final(rd_ptr == 0); | ||
full_aa: assert final(full == 0); | ||
empty_aa: assert final(empty == 1); | ||
underflow_aa: assert final(underflow == 0); | ||
almostfull_aa: assert final(almostfull == 0); | ||
almostempty_aa: assert final(almostempty == 0); | ||
wr_ack_aa: assert final(wr_ack == 0); | ||
overflow_aa: assert final(overflow == 0); | ||
`endif | ||
end | ||
if((count == FIFO_DEPTH)) | ||
`ifdef SIM | ||
full_a: assert final(full == 1); | ||
`endif | ||
if((count == 0)) | ||
`ifdef SIM | ||
empty_a: assert final(empty == 1); | ||
`endif | ||
if((count == FIFO_DEPTH - 1)) | ||
`ifdef SIM | ||
almostfull_a: assert final(almostfull == 1); | ||
`endif | ||
if((count == 1)) | ||
`ifdef SIM | ||
almostempty_a: assert final(almostempty == 1); | ||
`endif | ||
end | ||
// output flags | ||
property ack_p; | ||
@(posedge clk) disable iff (rst_n == 0) wr_en && (count < FIFO_DEPTH) |=> wr_ack ; | ||
endproperty | ||
|
||
property overflow_p; | ||
@(posedge clk) disable iff (rst_n == 0) ((count == FIFO_DEPTH) && wr_en) |=> (overflow == 1); | ||
endproperty | ||
|
||
property underflow_p; | ||
@(posedge clk) disable iff (rst_n == 0) (empty) && (rd_en) |=> underflow; | ||
endproperty // here | ||
|
||
// internal signals | ||
property wr_ptr_p; | ||
@(posedge clk) disable iff (rst_n == 0) (wr_en) && (count < FIFO_DEPTH) |=> (wr_ptr == $past(wr_ptr) + 1'b1); | ||
endproperty | ||
|
||
property rd_ptr_p; | ||
@(posedge clk) disable iff (rst_n == 0) (rd_en) && (count != 0) |=> (rd_ptr == $past(rd_ptr) + 1'b1); | ||
endproperty | ||
|
||
property count_write_priority_p; | ||
@(posedge clk) disable iff (rst_n == 0) (wr_en) && (rd_en) && (empty) |=> (count == $past(count) + 1); | ||
endproperty | ||
|
||
property count_read_priority_p; | ||
@(posedge clk) disable iff (rst_n == 0) (wr_en) && (rd_en) && (full) |=> (count == $past(count) - 1); | ||
endproperty | ||
|
||
property count_w_p; | ||
@(posedge clk) disable iff (rst_n == 0) (wr_en) && (!rd_en) && (!full) |=> (count == $past(count) + 1); | ||
endproperty | ||
|
||
property count_r_p; | ||
@(posedge clk) disable iff (rst_n == 0) (!wr_en) && (rd_en) && (!empty) |=> (count == $past(count) - 1); | ||
endproperty | ||
|
||
// Garded Assertions | ||
`ifdef SIM | ||
ack_a: assert property (ack_p); | ||
overflow_a: assert property (overflow_p); | ||
underflow_a: assert property (underflow_p); | ||
wr_ptr_a: assert property (wr_ptr_p); | ||
rd_ptr_a: assert property (rd_ptr_p); | ||
count_write_priority_a: assert property (count_write_priority_p); | ||
count_read_priority_a: assert property (count_read_priority_p); | ||
count_w_a: assert property (count_w_p); | ||
count_r_a: assert property (count_r_p); | ||
`endif | ||
|
||
// cover | ||
ack_c: cover property (ack_p); | ||
overflow_c: cover property (overflow_p); | ||
underflow_c: cover property (underflow_p); | ||
wr_ptr_c: cover property (wr_ptr_p); | ||
rd_ptr_c: cover property (rd_ptr_p); | ||
count_write_priority_c: cover property (count_write_priority_p); | ||
count_read_priority_c: cover property (count_read_priority_p); | ||
count_w_c: cover property (count_w_p); | ||
count_r_c: cover property (count_r_p); | ||
|
||
always @(posedge clk or negedge rst_n) begin | ||
if (!rst_n) begin | ||
wr_ptr <= 0; | ||
wr_ack <= 0; // was added | ||
overflow <= 0; // was added | ||
end | ||
else if (wr_en && count < FIFO_DEPTH) begin | ||
mem[wr_ptr] <= data_in; | ||
wr_ack <= 1; | ||
wr_ptr <= wr_ptr + 1; | ||
overflow <= 0; // was added | ||
end | ||
else begin | ||
wr_ack <= 0; | ||
if (full & wr_en) | ||
overflow <= 1; | ||
else | ||
overflow <= 0; | ||
end | ||
end | ||
|
||
always @(posedge clk or negedge rst_n) begin | ||
if (!rst_n) begin | ||
rd_ptr <= 0; | ||
underflow <= 0; // was added | ||
end | ||
else if (rd_en && count != 0) begin | ||
data_out <= mem[rd_ptr]; | ||
rd_ptr <= rd_ptr + 1; | ||
underflow <= 0; // was added | ||
end | ||
else begin | ||
if(empty && rd_en) // this is sequential output not combinational | ||
underflow = 1; | ||
else | ||
underflow = 0; | ||
end | ||
end | ||
|
||
always @(posedge clk or negedge rst_n) begin | ||
if (!rst_n) begin | ||
count <= 0; | ||
end | ||
else begin | ||
if (wr_en && rd_en && empty) // this condition was added | ||
count <= count + 1; | ||
else if (wr_en && rd_en && full) // this condition was added | ||
count <= count - 1; | ||
else if ( ({wr_en, rd_en} == 2'b10) && !full) | ||
count <= count + 1; | ||
else if ( ({wr_en, rd_en} == 2'b01) && !empty) | ||
count <= count - 1; | ||
end | ||
end | ||
|
||
assign full = (count == FIFO_DEPTH)? 1 : 0; | ||
assign empty = (count == 0)? 1 : 0; | ||
//assign underflow = (empty && rd_en)? 1 : 0; // this was synchronized | ||
assign almostfull = (count == FIFO_DEPTH-1)? 1 : 0; | ||
assign almostempty = (count == 1)? 1 : 0; | ||
|
||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package fifo_coverage_pkg; | ||
import fifo_transaction_pkg::*; | ||
import shared_pkg::*; | ||
class FIFO_coverage; | ||
// fifo_transaction class object | ||
FIFO_transaction F_cvg_txn = new; | ||
|
||
|
||
// cover group | ||
covergroup FIFO_Cross_Group; // all crosses will be with read enable and write enable and each one of the output signals | ||
// cover points | ||
cp_wr_en: coverpoint F_cvg_txn.wr_en; | ||
cp_rd_en: coverpoint F_cvg_txn.rd_en; | ||
cp_ack: coverpoint F_cvg_txn.wr_ack; | ||
cp_overflow: coverpoint F_cvg_txn.overflow; | ||
cp_full: coverpoint F_cvg_txn.full; | ||
cp_empty: coverpoint F_cvg_txn.empty; | ||
cp_almostfull: coverpoint F_cvg_txn.almostfull; | ||
cp_almostempty: coverpoint F_cvg_txn.almostempty; | ||
cp_underflow: coverpoint F_cvg_txn.underflow; | ||
// cross coverage | ||
wr_ack_C: cross cp_wr_en, cp_rd_en, cp_ack{ | ||
illegal_bins zero_zero_one = binsof(cp_wr_en) intersect {0} && binsof(cp_ack) intersect {1}; | ||
} // cross coverage for wr_ack, note that a wr_ack can't be done if the wr_en is zero so i made this case illegal | ||
overflow_C: cross cp_wr_en, cp_rd_en, cp_overflow{ | ||
illegal_bins zero_w_one = binsof(cp_wr_en) intersect {0} && binsof(cp_overflow) intersect {1}; | ||
} // cross coverage for overflow, note that an overflow can't be done if there is no wr_en, so i made it illegal | ||
full_C: cross cp_wr_en, cp_rd_en, cp_full{ | ||
illegal_bins one_r_one = binsof(cp_rd_en) intersect {1} && binsof(cp_full) intersect {1}; | ||
} // cross coverage for full, note that a full signal can't be riased if there is read process, so i made it illegal | ||
empty_C: cross cp_wr_en, cp_rd_en, cp_empty; // cross coverage for empty | ||
almostfull_C: cross cp_wr_en, cp_rd_en, cp_almostfull; // cross coverage for almostfull signal | ||
almostempty_C: cross cp_wr_en, cp_rd_en, cp_almostempty; // cross coverage for almostempty signal | ||
underflow_C: cross cp_wr_en, cp_rd_en, cp_underflow{ | ||
illegal_bins zero_r_one = binsof(cp_rd_en) intersect {0} && binsof(cp_underflow) intersect {1}; | ||
} // cross coverage for underflow signal, note that an underflow can't be done if no read operation occurs, so i made it illegal | ||
endgroup | ||
|
||
// void function | ||
function void sample_data(FIFO_transaction F_txn); | ||
F_cvg_txn = F_txn; | ||
FIFO_Cross_Group.sample(); | ||
endfunction | ||
|
||
function new(); | ||
FIFO_Cross_Group = new(); | ||
endfunction | ||
endclass | ||
endpackage | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
interface fifo_if (clk); | ||
input clk; | ||
|
||
parameter FIFO_WIDTH = 16; | ||
parameter FIFO_DEPTH = 8; | ||
|
||
// signals | ||
logic [FIFO_WIDTH-1:0] data_in; | ||
logic rst_n, wr_en, rd_en; | ||
logic [FIFO_WIDTH-1:0] data_out; | ||
logic wr_ack, overflow; | ||
logic full, empty, almostfull, almostempty, underflow; | ||
|
||
// dut module | ||
modport DUT ( | ||
input clk, data_in, rst_n, wr_en, rd_en, | ||
output data_out, wr_ack, overflow, full, empty, almostfull, almostempty, underflow | ||
); | ||
// test module | ||
modport TEST ( | ||
output data_in, rst_n, wr_en, rd_en, | ||
input clk, data_out, wr_ack, overflow, full, empty, almostfull, almostempty, underflow | ||
); | ||
// monitor module | ||
modport MONITOR ( | ||
input clk, data_in, rst_n, wr_en, rd_en, data_out, wr_ack, overflow, full, empty, almostfull, almostempty, underflow | ||
); | ||
endinterface |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import fifo_transaction_pkg::*; | ||
import fifo_coverage_pkg::*; | ||
import fifo_scoreboard_pkg::*; | ||
import shared_pkg::*; | ||
module fifo_monitor (fifo_if.MONITOR fifoif); | ||
FIFO_transaction tr_mon = new; // transaction object | ||
FIFO_coverage cov_mon = new; // coverage object | ||
FIFO_scoreboard scb_mon = new; // scoreboard object | ||
|
||
initial begin | ||
forever begin | ||
#20; // negedge | ||
// assigning interface data to class transaction object | ||
tr_mon.data_in = fifoif.data_in; | ||
tr_mon.rst_n = fifoif.rst_n; | ||
tr_mon.wr_en = fifoif.wr_en; | ||
tr_mon.rd_en = fifoif.rd_en; | ||
tr_mon.data_out = fifoif.data_out; | ||
tr_mon.wr_ack = fifoif.wr_ack; | ||
tr_mon.overflow = fifoif.overflow; | ||
tr_mon.full = fifoif.full; | ||
tr_mon.empty = fifoif.empty; | ||
tr_mon.almostfull = fifoif.almostfull; | ||
tr_mon.almostempty = fifoif.almostempty; | ||
tr_mon.underflow = fifoif.underflow; | ||
// two parallel processes | ||
fork | ||
// process 1 | ||
cov_mon.sample_data(tr_mon); | ||
// process 2 | ||
scb_mon.check_data(tr_mon); | ||
join | ||
if (test_finished) begin | ||
$display("error count = %0d, correct count = %0d", error_count_out, correct_count_out); | ||
$stop; | ||
end | ||
end | ||
end | ||
endmodule | ||
|
Oops, something went wrong.