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/trunk/rtl
- from Rev 2 to Rev 3
- ↔ Reverse comparison
Rev 2 → Rev 3
/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 |
/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 |
/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 |