Commit 76fb3867 authored by Guillem's avatar Guillem
Browse files

add missing files previous commit

parent 318a8a90
`define START_GREEN_PRINT $write("%c[1;32m",27);
`define START_RED_PRINT $write("%c[1;31m",27);
`define END_COLOR_PRINT $write("%c[0m",27);
//
// Synchronous FIFO
//
// Freeware September 2015, Fen Logic Ltd.
// This code is free and is delivered 'as is'.
// It comes without any warranty, to the extent permitted by applicable law.
// There are no restrictions to any use or re-use of this code
// in any form or shape. It would be nice if you keep my company name
// in the source or modified source code but even that is not
// required as I can't check it anyway.
// But the code comes with no warranties or guarantees whatsoever.
//
// Read and Write are ignored when empty/full
// The fifo level is registered
// The full, empty flags can be registered or not
//
// Known issues:
// artithmetic is not size compliant (pntr <= pntr + {{(L2D-1){1'b0}},1'b1};)
// Storage contents is not cleared
// relying on synthesis tool to remove unused logic
//
module sync_fifo
#(parameter WIDTH = 8, // width in bits
L2D = 4, // Log 2 Depth, 4=16 deep
REGFLAGS = 1 // Full, empty are registered
)
(
input clk, // system clock
input reset_n, // A-synchronous low reset/clear
input enable, // clock gating
input clear, // Synchronous clear
input write, // write FIFO
input [WIDTH-1:0] wdata, // write data
input read, // read FIFO
output [WIDTH-1:0] rdata, // read data
output reg empty, // FIFO is empty
output reg full, // FIFO is full
output reg [L2D:0] level // Fill level
);
localparam DEPTH = (1<<L2D);
reg [WIDTH-1:0] memory [0:DEPTH-1];
reg [L2D-1:0] rd_pntr,wt_pntr;
reg full_r,empty_r;
wire l_read,l_write;
// prevent disastrous reads & writes
assign l_read = read & !empty;
assign l_write = write & !full;
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
begin
rd_pntr <= {L2D{1'b0}};
wt_pntr <= {L2D{1'b0}};
level <= {L2D{1'b0}};
full_r <= 1'b0;
empty_r <= 1'b1;
end
else if (enable)
begin
if (clear)
begin
rd_pntr <= {L2D{1'b0}};
wt_pntr <= {L2D{1'b0}};
level <= {L2D{1'b0}};
full_r <= 1'b0;
empty_r <= 1'b1;
end
else
begin
case ({l_read,l_write})
2'b01 : // Write, no read
begin
wt_pntr <= wt_pntr + 1;
level <= level + 1;
full_r <= (level==DEPTH-1);
empty_r <= 1'b0;
end
2'b10 : // Read, no write
begin
rd_pntr <= rd_pntr + 1;
level <= level - 1;
full_r <= 1'b0;
empty_r <= (level==1);
end
2'b11 : // Read & Write
begin
wt_pntr <= wt_pntr + 1;
rd_pntr <= rd_pntr + 1;
end
endcase
end
`ifdef ASSERT_ON
// Catch fatal operational errors
if (write && !l_write)
begin
$display("%m,@%0t: write to full FIFO",$time);
#1 $stop;
end
if (read && !l_read)
begin
$display("%m,@%0t: read from empty FIFO",$time);
#1 $stop;
end
`endif
end
end
// Write to fifo
always @(posedge clk)
begin
if (enable & l_write)
memory[wt_pntr] <= wdata;
end
// Read from fifo:
assign rdata = memory[rd_pntr];
// empty and full flags depend on parameter
// registered or not
always @( * )
begin
if (REGFLAGS==0)
begin
full = (level==DEPTH);
empty = (level==0);
end
else
begin
full = full_r;
empty = empty_r;
end
end
endmodule
\ No newline at end of file
//
// A-synchronous FIFO level test
//
//
// Freeware September 2015, Fen Logic Ltd.
// This code is free and is delivered 'as is'.
// It comes without any warranty, to the extent permitted by applicable law.
// There are no restrictions to any use or re-use of this code
// in any form or shape. It would be nice if you keep my company name
// in the source or modified source code but even that is not
// required as I can't check it anyway.
// But the code comes with no warranties or guarantees whatsoever.
//
module async_fifo_level_test;
localparam CLK_PERIOD=100;
localparam WI = 16;
localparam L2D= 4;
reg clk;
reg reset_n;
reg [WI-1:0] w_data;
reg w_strobe;
wire w_full;
wire [L2D:0] w_level;
wire [WI-1:0] r_data;
reg r_strobe;
wire r_empty;
wire [L2D:0] r_level;
integer i,rnd,wt,rd;
integer wl,rl;
initial
begin
reset_n = 1'b0;
w_strobe = 1'b0;
r_strobe = 1'b0;
w_data = 16'h1234;
wl=0;
rl=0;
#(CLK_PERIOD*10) ;
@(posedge clk) #5;
reset_n = 1'b1;
#(CLK_PERIOD*4) ;
for (i=0; i<1000000; i=i+1)
begin
rnd = $random;
wt=0;
if (rnd & 1)
begin
if (!w_full)
begin
w_strobe = 1'b1;
wt = 1;
end
end
rd=0;
if (rnd & 2)
begin
if (!r_empty)
begin
r_strobe = 1'b1;
rd = 1;
end
end
#CLK_PERIOD ;
// One cycle later the effect of the read and write is present
if (wt)
wl = wl + 1;
if (rd)
rl =rl - 1;
if (w_level!=wl)
begin
$display("@%0t: Direct write level error",$time);
#10 $stop;
end
if (r_level!=rl)
begin
$display("@%0t: Direct read level error",$time);
#10 $stop;
end
w_strobe = 1'b0;
r_strobe = 1'b0;
#CLK_PERIOD ;
#CLK_PERIOD ;
// two cycles later the effect of the 'other' port arrives
if (rd)
wl = wl - 1;
if (wt)
rl =rl + 1;
if (w_level!=wl)
begin
$display("@%0t: Delayed write level error",$time);
#10 $stop;
end
if (r_level!=rl)
begin
$display("@%0t: Delayed read level error",$time);
#10 $stop;
end
#CLK_PERIOD ;
#CLK_PERIOD ;
end
$display("FIFO level test passed");
$stop;
end
async_fifo
#(
.WI (WI) ,
.L2D (L2D)
) // parameters
async_fifo_inst (
.reset_n (reset_n),
.w_clk (clk),
.w_data (w_data),
.w_strobe(w_strobe),
.w_full (w_full),
.w_level (w_level),
.r_clk (clk),
.r_data (r_data),
.r_strobe(r_strobe),
.r_empty (r_empty),
.r_level (r_level)
);
// Generate clock.
initial
begin
clk = 1'b0;
forever
#(CLK_PERIOD/2) clk = ~clk;
end
endmodule
//
// A-synchronous FIFO with library cells test
// This behavioural test tries to shake out any a-synchtonisity errors.
//
//
//
// Freeware September 2015, Fen Logic Ltd.
// This code is free and is delivered 'as is'.
// It comes without any warranty, to the extent permitted by applicable law.
// There are no restrictions to any use or re-use of this code
// in any form or shape. It would be nice if you keep my company name
// in the source or modified source code but even that is not
// required as I can't check it anyway.
// But the code comes with no warranties or guarantees whatsoever.
//
module async_fifo_lib_test;
localparam WCLK_PERIOD=208;
localparam RCLK_PERIOD=200;
localparam WI = 16;
localparam L2D= 4;
localparam LMAX = (1<<L2D);
reg wclk;
reg rclk;
reg reset_n;
reg [WI-1:0] w_data;
reg w_strobe;
wire w_full;
wire [L2D:0] w_level;
wire [WI-1:0] r_data;
reg r_strobe;
wire r_empty;
wire [L2D:0] r_level;
integer i;
reg [WI-1:0] exp_r_data;
initial
begin
reset_n = 1'b0;
#(WCLK_PERIOD*10) ;
@(posedge wclk) #5;
reset_n = 1'b1;
#(WCLK_PERIOD*4) ;
for (i=0; i<1000000; i=i+1)
#(WCLK_PERIOD*40) ;
$display("FIFO test passed");
$stop;
end
always @(posedge wclk or negedge reset_n)
begin
if (!reset_n)
begin
w_strobe <= 1'b0;
w_data <= 0;
end
else
begin
w_strobe <= 1'b0;
if ($random & 4)
begin
if (!w_full && !(w_level==LMAX-1 & w_strobe))
begin
w_strobe <= 1'b1;
w_data <= w_data + 1;
end
end // do write
end // clocked
end // always
always @(posedge rclk or negedge reset_n)
begin
if (!reset_n)
begin
r_strobe <= 1'b0;
exp_r_data <= 1;
end
else
begin
r_strobe <= 1'b0;
if ($random & 8)
begin
if (!r_empty && !(r_level==1 & r_strobe))
r_strobe <= 1'b1;
end // do read
if (r_strobe)
begin
exp_r_data <= exp_r_data + 1;
if (exp_r_data!==r_data)
begin
$display("@%0t read mismatch. Have 0x%4X, expected 0x%04x",
$time,r_data,exp_r_data);
#210 $stop;
end
end // was read
end // clocked
end // always
async_fifo_lib
#(
.WI (WI) ,
.L2D (L2D)
) // parameters
async_fifo_lib_inst (
.reset_n (reset_n),
.w_clk (wclk),
.w_data (w_data),
.w_strobe(w_strobe),
.w_full (w_full),
.w_level (w_level),
.r_clk (rclk),
.r_data (r_data),
.r_strobe(r_strobe),
.r_empty (r_empty),
.r_level (r_level)
);
// Generate clocks
initial
begin
wclk = 1'b0;
forever
#(WCLK_PERIOD/2) wclk = ~wclk;
end
initial
begin
rclk = 1'b0;
forever
#(RCLK_PERIOD/2) rclk = ~rclk;
end
endmodule
//
// Model of a synchronisation cell
// (Rising edge to rising edge, two registers)
//
// Freeware September 2015, Fen Logic Ltd.
// This code is free and is delivered 'as is'.
// It comes without any warranty, to the extent permitted by applicable law.
// There are no restrictions to any use or re-use of this code
// in any form or shape. It would be nice if you keep my company name
// in the source or modified source code but even that is not
// required as I can't check it anyway.
// But the code comes with no warranties or guarantees whatsoever.
//
module lib_sync_cell (
input CLK,
input CLRn,
input D,
output reg Q
);
`ifdef FIFO_SIM_ASYNC
// Simulate a-synchronous behaviour:
// FFs will clock data in at a different time
// Generate a random constant delay
// in the range 0..15
time d;
initial
d = $random() & 32'h00F;
reg delta;
always @(D)
delta <= #d D;
`endif
reg meta;
always @(posedge CLK or negedge CLRn)
begin
if (!CLRn)
begin
meta <= 1'b0;
Q <= 1'b0;
end
else
begin
`ifdef FIFO_SIM_ASYNC
meta <= delta;
`else
meta <= D;
`endif
Q <= meta;
end
end
endmodule
\ No newline at end of file
//
// Synchronous FIFO test
// Half data width FIFO
//
//
// Freeware September 2015, Fen Logic Ltd.
// This code is free and is delivered 'as is'.
// It comes without any warranty, to the extent permitted by applicable law.
// There are no restrictions to any use or re-use of this code
// in any form or shape. It would be nice if you keep my company name
// in the source or modified source code but even that is not
// required as I can't check it anyway.
// But the code comes with no warranties or guarantees whatsoever.
//
`define ASSERT_ON
module sync_fifo_dd_test;
localparam CLK_PERIOD=100;
localparam WI = 8;
localparam DEPTH = 16;
localparam LEVLBITS = 5; // 0..16
reg clk;
reg reset_n;
reg enable;
reg clear;
reg [WI-1:0] wdata;
reg write;
wire empty;
wire full ;
wire [LEVLBITS-1:0] level;
wire [WI*2-1:0] rdata;
reg read;
integer i;
reg [WI*2-1:0] exp_rdata;
initial
begin
reset_n = 1'b0;
enable = 1'b1;
clear = 1'b0;
#(CLK_PERIOD*10) ;
@(posedge clk) #5;
reset_n = 1'b1;
#(CLK_PERIOD*4) ;
for (i=0; i<1000000; i=i+1)
#(CLK_PERIOD*4) ;
$display("FIFO test passed");
$stop;
end
sync_fifo_dd
#(
.WI (WI) ,
.DEPTH (DEPTH),
.LEVLBITS(LEVLBITS),
.REGFLAGS(1) // !! Run test twice:REGFLAGS=0 & REGFLAGS=1
) // parameters
sync_fifo_dd_inst (
.clk (clk),
.reset_n (reset_n),
.enable (enable),
.clear (clear),
.wdata (wdata),
.write (write),
.rdata (rdata),
.read (read),
.full (full),
.empty (empty),
.level (level)
);
always @(posedge clk or negedge reset_n)
begin
if (!reset_n)
begin
write <= 1'b0;
wdata <= 8'hFF; //
end
else
begin
write <= 1'b0;
if ($random & 3)
begin
if (!full && !(level==DEPTH-1 & write))