URL
https://opencores.org/ocsvn/srdydrdy_lib/srdydrdy_lib/trunk
Subversion Repositories srdydrdy_lib
Compare Revisions
- This comparison shows the changes necessary to convert path
/srdydrdy_lib
- from Rev 2 to Rev 3
- ↔ Reverse comparison
Rev 2 → Rev 3
/trunk/rtl/verilog/buffers/sd_fifo_s.v
0,0 → 1,121
//---------------------------------------------------------------------- |
// Srdy/Drdy FIFO "S" |
// |
// Building block for FIFOs. The "S" (small or synchronizer) FIFO is |
// designed for smaller FIFOs based around memories or flops, with |
// sizes that are a power of 2. |
// |
// The "S" FIFO can be used as a two-clock asynchronous FIFO. When the |
// async parameter is set to 1, the pointers will be converted from |
// binary to grey code and double-synchronized. |
// |
// Naming convention: c = consumer, p = producer, i = internal interface |
//---------------------------------------------------------------------- |
// Author: Guy Hutchison |
// |
// This block is uncopyrighted and released into the public domain. |
//---------------------------------------------------------------------- |
|
// delay unit for nonblocking assigns, default is to #1 |
`ifndef SDLIB_DELAY |
`define SDLIB_DELAY #1 |
`endif |
|
module sd_fifo_s |
#(parameter width=8, |
parameter depth=16, |
parameter async=0 |
) |
( |
input c_clk, |
input c_reset, |
input c_srdy, |
output c_drdy, |
input [width-1:0] c_data, |
|
input p_clk, |
input p_reset, |
output p_srdy, |
input p_drdy, |
output [width-1:0] p_data |
); |
|
localparam asz = $clog2(depth); |
|
reg [width-1:0] mem [0:depth-1]; |
wire [width-1:0] mem_rddata; |
wire rd_en; |
wire [asz:0] rdptr_tail, rdptr_tail_sync; |
wire wr_en; |
wire [asz:0] wrptr_head, wrptr_head_sync; |
reg [width-1:0] p_data; |
reg dly_rd_en; |
wire [asz-1:0] rd_addr, wr_addr; |
|
always @(posedge c_clk) |
if (wr_en) |
mem[wr_addr] <= `SDLIB_DELAY c_data; |
|
assign mem_rddata = mem[rd_addr]; |
|
sd_fifo_head_s #(depth, async) head |
( |
// Outputs |
.c_drdy (c_drdy), |
.wrptr_head (wrptr_head), |
.wr_en (wr_en), |
.wr_addr (wr_addr), |
// Inputs |
.clk (c_clk), |
.reset (c_reset), |
.c_srdy (c_srdy), |
.rdptr_tail (rdptr_tail_sync)); |
|
sd_fifo_tail_s #(depth, async) tail |
( |
// Outputs |
.rdptr_tail (rdptr_tail), |
.rd_en (rd_en), |
.rd_addr (rd_addr), |
.p_srdy (p_srdy), |
// Inputs |
.clk (p_clk), |
.reset (p_reset), |
.wrptr_head (wrptr_head_sync), |
.p_drdy (p_drdy)); |
|
always @(posedge p_clk) |
begin |
if (rd_en) |
p_data <= `SDLIB_DELAY mem_rddata; |
end |
|
generate |
if (async) |
begin : gen_sync |
reg [asz:0] r_sync1, r_sync2; |
reg [asz:0] w_sync1, w_sync2; |
|
always @(posedge p_clk) |
begin |
w_sync1 <= `SDLIB_DELAY wrptr_head; |
w_sync2 <= `SDLIB_DELAY w_sync1; |
end |
|
always @(posedge c_clk) |
begin |
r_sync1 <= `SDLIB_DELAY rdptr_tail; |
r_sync2 <= `SDLIB_DELAY r_sync1; |
end |
|
assign wrptr_head_sync = w_sync2; |
assign rdptr_tail_sync = r_sync2; |
end |
else |
begin : gen_nosync |
assign wrptr_head_sync = wrptr_head; |
assign rdptr_tail_sync = rdptr_tail; |
end |
endgenerate |
|
endmodule // sd_fifo_s |
/trunk/rtl/verilog/buffers/sd_fifo_head_s.v
0,0 → 1,103
//---------------------------------------------------------------------- |
// Srdy/Drdy FIFO Head "S" |
// |
// Building block for FIFOs. The "S" (big) FIFO is design for smaller |
// FIFOs based around memories or flops, with sizes that are a power of 2. |
// |
// The "S" FIFO can be used as a two-clock asynchronous FIFO. |
// |
// Naming convention: c = consumer, p = producer, i = internal interface |
//---------------------------------------------------------------------- |
// Author: Guy Hutchison |
// |
// This block is uncopyrighted and released into the public domain. |
//---------------------------------------------------------------------- |
|
// Clocking statement for synchronous blocks. Default is for |
// posedge clocking and positive async reset |
`ifndef SDLIB_CLOCKING |
`define SDLIB_CLOCKING posedge clk or posedge reset |
`endif |
|
// delay unit for nonblocking assigns, default is to #1 |
`ifndef SDLIB_DELAY |
`define SDLIB_DELAY #1 |
`endif |
|
module sd_fifo_head_s |
#(parameter depth=16, |
parameter async=0, |
parameter asz=$clog2(depth) |
) |
( |
input clk, |
input reset, |
input c_srdy, |
output c_drdy, |
|
output [asz:0] wrptr_head, |
output [asz-1:0] wr_addr, |
output reg wr_en, |
input [asz:0] rdptr_tail |
|
); |
|
reg [asz:0] wrptr, nxt_wrptr; |
reg [asz:0] wrptr_p1; |
reg empty, full; |
wire [asz:0] rdptr; |
|
assign c_drdy = !full; |
assign wr_addr = wrptr[asz-1:0]; |
|
always @* |
begin |
wrptr_p1 = wrptr + 1; |
|
full = ((wrptr[asz-1:0] == rdptr[asz-1:0]) && |
(wrptr[asz] == ~rdptr[asz])); |
|
if (c_srdy & !full) |
nxt_wrptr = wrptr_p1; |
else |
nxt_wrptr = wrptr; |
|
wr_en = (c_srdy & !full); |
end |
|
always @(`SDLIB_CLOCKING) |
begin |
if (reset) |
begin |
wrptr <= `SDLIB_DELAY 0; |
end |
else |
begin |
wrptr <= `SDLIB_DELAY nxt_wrptr; |
end // else: !if(reset) |
end // always @ (posedge clk) |
|
function [asz:0] bin2grey; |
input [asz:0] bin_in; |
integer b; |
begin |
bin2grey[asz] = bin_in[asz]; |
for (b=0; b<asz; b=b+1) |
bin2grey[b] = bin_in[b] ^ bin_in[b+1]; |
end |
endfunction // for |
|
function [asz:0] grey2bin; |
input [asz:0] grey_in; |
integer b; |
begin |
grey2bin[asz] = grey_in[asz]; |
for (b=asz-1; b>=0; b=b-1) |
grey2bin[b] = grey_in[b] ^ grey2bin[b+1]; |
end |
endfunction |
|
assign wrptr_head = (async) ? bin2grey(wrptr) : wrptr; |
assign rdptr = (async)? grey2bin(rdptr_tail) : rdptr_tail; |
|
endmodule |
/trunk/rtl/verilog/buffers/sd_fifo_tail_s.v
0,0 → 1,107
//---------------------------------------------------------------------- |
// Srdy/Drdy FIFO Head "S" |
// |
// Building block for FIFOs. The "S" (big) FIFO is design for smaller |
// FIFOs based around memories or flops, with sizes that are a power of 2. |
// |
// The "S" FIFO can be used as a two-clock asynchronous FIFO. |
// |
// Naming convention: c = consumer, p = producer, i = internal interface |
//---------------------------------------------------------------------- |
// Author: Guy Hutchison |
// |
// This block is uncopyrighted and released into the public domain. |
//---------------------------------------------------------------------- |
|
// Clocking statement for synchronous blocks. Default is for |
// posedge clocking and positive async reset |
`ifndef SDLIB_CLOCKING |
`define SDLIB_CLOCKING posedge clk or posedge reset |
`endif |
|
// delay unit for nonblocking assigns, default is to #1 |
`ifndef SDLIB_DELAY |
`define SDLIB_DELAY #1 |
`endif |
|
module sd_fifo_tail_s |
#(parameter depth=16, |
parameter async=0, |
parameter asz=$clog2(depth) |
) |
( |
input clk, |
input reset, |
|
input [asz:0] wrptr_head, |
output [asz:0] rdptr_tail, |
|
output reg rd_en, |
output [asz-1:0] rd_addr, |
|
output reg p_srdy, |
input p_drdy |
); |
|
reg [asz:0] rdptr; |
reg [asz:0] nxt_rdptr; |
reg [asz:0] rdptr_p1; |
reg empty; |
reg nxt_p_srdy; |
wire [asz:0] wrptr; |
|
assign rd_addr = nxt_rdptr[asz-1:0]; |
|
always @* |
begin |
rdptr_p1 = rdptr + 1; |
|
empty = (wrptr == rdptr); |
|
if (p_drdy & p_srdy) |
nxt_rdptr = rdptr_p1; |
else |
nxt_rdptr = rdptr; |
|
nxt_p_srdy = (wrptr != nxt_rdptr); |
rd_en = (p_drdy & p_srdy) | (!empty & !p_srdy); |
end |
|
always @(`SDLIB_CLOCKING) |
begin |
if (reset) |
begin |
rdptr <= `SDLIB_DELAY 0; |
p_srdy <= `SDLIB_DELAY 0; |
end |
else |
begin |
rdptr <= `SDLIB_DELAY nxt_rdptr; |
p_srdy <= `SDLIB_DELAY nxt_p_srdy; |
end // else: !if(reset) |
end // always @ (posedge clk) |
|
function [asz:0] bin2grey; |
input [asz:0] bin_in; |
integer b; |
begin |
bin2grey[asz] = bin_in[asz]; |
for (b=0; b<asz; b=b+1) |
bin2grey[b] = bin_in[b] ^ bin_in[b+1]; |
end |
endfunction // for |
|
function [asz:0] grey2bin; |
input [asz:0] grey_in; |
integer b; |
begin |
grey2bin[asz] = grey_in[asz]; |
for (b=asz-1; b>=0; b=b-1) |
grey2bin[b] = grey_in[b] ^ grey2bin[b+1]; |
end |
endfunction |
|
assign rdptr_tail = (async) ? bin2grey(rdptr) : rdptr; |
assign wrptr = (async)? grey2bin(wrptr_head) : wrptr_head; |
|
endmodule // sd_fifo_head_s |
/trunk/env/verilog/sd_seq_check.v
0,0 → 1,99
//---------------------------------------------------------------------- |
// Srdy/Drdy sequence checker |
// |
// Simplistic traffic checker for srdy/drdy blocks. Checks for an |
// incrementing data sequence. |
// |
// Naming convention: c = consumer, p = producer, i = internal interface |
//---------------------------------------------------------------------- |
// Author: Guy Hutchison |
// |
// This block is uncopyrighted and released into the public domain. |
//---------------------------------------------------------------------- |
|
// delay unit for nonblocking assigns, default is to #1 |
`ifndef SDLIB_DELAY |
`define SDLIB_DELAY #1 |
`endif |
|
module sd_seq_check |
#(parameter width=8) |
(input clk, |
input reset, |
input c_srdy, |
output reg c_drdy, |
input [width-1:0] c_data); |
|
parameter pat_dep = 8; |
|
reg [width-1:0] last_seq; |
reg first; |
reg [pat_dep-1:0] drdy_pat; |
integer dpp; |
reg nxt_c_drdy; |
|
initial |
begin |
drdy_pat = {pat_dep{1'b1}}; |
dpp = 0; |
end |
|
initial |
begin |
first = 1; |
c_drdy = 0; |
end |
|
always @* |
begin |
nxt_c_drdy = c_drdy; |
|
if (c_srdy & c_drdy) |
begin |
if (drdy_pat[dpp]) |
begin |
nxt_c_drdy = 1; |
end |
else |
nxt_c_drdy = 0; |
end |
else if (!c_drdy) |
begin |
if (drdy_pat[dpp]) |
begin |
nxt_c_drdy = 1; |
end |
else |
nxt_c_drdy = 0; |
end |
end |
always @(posedge clk) |
begin |
if ((c_srdy & c_drdy) | !c_drdy) |
dpp = (dpp + 1) % pat_dep; |
end |
|
always @(posedge clk) |
begin |
if (reset) |
begin |
c_drdy <= `SDLIB_DELAY 0; |
end |
else |
begin |
c_drdy <= `SDLIB_DELAY nxt_c_drdy; |
if (c_srdy & c_drdy) |
begin |
if (!first && (c_data !== (last_seq + 1))) |
$display ("%t: ERROR : %m: Sequence miscompare rcv=%x exp=%x", |
$time, c_data, last_seq+1); |
else |
begin |
last_seq = c_data; |
first = 0; |
end |
end // if (c_srdy & c_drdy) |
end // else: !if(reset) |
end |
|
endmodule // sd_seq_check |
/trunk/env/verilog/bench_fifo_s.v
0,0 → 1,109
`timescale 1ns/1ns |
|
module bench_fifo_s; |
|
reg clk, reset; |
|
localparam width = 8; |
|
initial clk = 0; |
always #10 clk = ~clk; |
|
/*AUTOWIRE*/ |
// Beginning of automatic wires (for undeclared instantiated-module outputs) |
wire [width-1:0] chk_data; // From fifo_s of sd_fifo_s.v |
wire chk_drdy; // From chk of sd_seq_check.v |
wire chk_srdy; // From fifo_s of sd_fifo_s.v |
wire [width-1:0] gen_data; // From gen of sd_seq_gen.v |
wire gen_drdy; // From fifo_s of sd_fifo_s.v |
wire gen_srdy; // From gen of sd_seq_gen.v |
// End of automatics |
|
/* sd_seq_gen AUTO_TEMPLATE |
( |
.p_\(.*\) (gen_\1[]), |
); |
*/ |
sd_seq_gen gen |
(/*AUTOINST*/ |
// Outputs |
.p_srdy (gen_srdy), // Templated |
.p_data (gen_data[width-1:0]), // Templated |
// Inputs |
.clk (clk), |
.reset (reset), |
.p_drdy (gen_drdy)); // Templated |
|
/* sd_seq_check AUTO_TEMPLATE |
( |
.c_\(.*\) (chk_\1[]), |
); |
*/ |
sd_seq_check chk |
(/*AUTOINST*/ |
// Outputs |
.c_drdy (chk_drdy), // Templated |
// Inputs |
.clk (clk), |
.reset (reset), |
.c_srdy (chk_srdy), // Templated |
.c_data (chk_data[width-1:0])); // Templated |
|
/* sd_fifo_s AUTO_TEMPLATE |
( |
.c_clk (clk), |
.c_reset (reset), |
.p_clk (clk), |
.p_reset (reset), |
.p_\(.*\) (chk_\1[]), |
.c_\(.*\) (gen_\1[]), |
); |
*/ |
sd_fifo_s #(8, 32, 1) fifo_s |
(/*AUTOINST*/ |
// Outputs |
.c_drdy (gen_drdy), // Templated |
.p_srdy (chk_srdy), // Templated |
.p_data (chk_data[width-1:0]), // Templated |
// Inputs |
.c_clk (clk), // Templated |
.c_reset (reset), // Templated |
.c_srdy (gen_srdy), // Templated |
.c_data (gen_data[width-1:0]), // Templated |
.p_clk (clk), // Templated |
.p_reset (reset), // Templated |
.p_drdy (chk_drdy)); // Templated |
|
initial |
begin |
$dumpfile("fifo_s.vcd"); |
$dumpvars; |
reset = 1; |
#100; |
reset = 0; |
|
// burst normal data for 20 cycles |
repeat (20) @(posedge clk); |
|
gen.srdy_pat = 8'h5A; |
repeat (20) @(posedge clk); |
|
chk.drdy_pat = 8'hA5; |
repeat (40) @(posedge clk); |
|
// check FIFO overflow |
gen.srdy_pat = 8'hFD; |
repeat (100) @(posedge clk); |
|
// check FIFO underflow |
gen.srdy_pat = 8'h11; |
repeat (100) @(posedge clk); |
|
#5000; |
$finish; |
end |
|
endmodule // bench_fifo_s |
// Local Variables: |
// verilog-library-directories:("." "../../rtl/verilog/buffers") |
// End: |
/trunk/env/verilog/sd_seq_gen.v
0,0 → 1,94
//---------------------------------------------------------------------- |
// Srdy/Drdy sequence generator |
// |
// Simplistic traffic generator for srdy/drdy blocks. Generates an |
// incrementing data sequence. |
// |
// Naming convention: c = consumer, p = producer, i = internal interface |
//---------------------------------------------------------------------- |
// Author: Guy Hutchison |
// |
// This block is uncopyrighted and released into the public domain. |
//---------------------------------------------------------------------- |
|
// delay unit for nonblocking assigns, default is to #1 |
`ifndef SDLIB_DELAY |
`define SDLIB_DELAY #1 |
`endif |
|
module sd_seq_gen |
#(parameter width=8) |
(input clk, |
input reset, |
output reg p_srdy, |
input p_drdy, |
output reg [width-1:0] p_data); |
|
reg nxt_p_srdy; |
reg [width-1:0] nxt_p_data; |
|
parameter pat_dep = 8; |
|
reg [pat_dep-1:0] srdy_pat; |
integer spp, startup; |
|
initial |
begin |
srdy_pat = {pat_dep{1'b1}}; |
spp = 0; |
startup = 0; |
end |
|
always @* |
begin |
nxt_p_data = p_data; |
nxt_p_srdy = p_srdy; |
|
if (startup < 10) |
begin |
end |
else if (p_srdy & p_drdy) |
begin |
if (srdy_pat[spp]) |
begin |
nxt_p_data = p_data + 1; |
nxt_p_srdy = 1; |
end |
else |
nxt_p_srdy = 0; |
end |
else if (!p_srdy) |
begin |
if (srdy_pat[spp]) |
begin |
nxt_p_data = p_data + 1; |
nxt_p_srdy = 1; |
end |
else |
nxt_p_srdy = 0; |
end |
end // always @ * |
|
always @(posedge clk) |
begin |
if ((p_srdy & p_drdy) | !p_srdy) |
spp = (spp + 1) % pat_dep; |
end |
|
always @(posedge clk) |
begin |
if (reset) |
begin |
p_srdy <= `SDLIB_DELAY 0; |
p_data <= `SDLIB_DELAY 0; |
end |
else |
begin |
p_srdy <= `SDLIB_DELAY nxt_p_srdy; |
p_data <= `SDLIB_DELAY nxt_p_data; |
if (startup < 10) |
startup = startup + 1; |
end |
end |
|
endmodule // sd_seq_gen |
/trunk/env/verilog/bench_fifo_s.vf
0,0 → 1,6
bench_fifo_s.v |
sd_seq_check.v |
sd_seq_gen.v |
../../rtl/verilog/buffers/sd_fifo_s.v |
../../rtl/verilog/buffers/sd_fifo_head_s.v |
../../rtl/verilog/buffers/sd_fifo_tail_s.v |