3 #(parameter DWIDTH=32, AWIDTH=9)
4 (input wclk, input [DWIDTH-1:0] datain, input write, output full, output reg [AWIDTH-1:0] level_wclk,
5 input rclk, output [DWIDTH-1:0] dataout, input read, output empty, output reg [AWIDTH-1:0] level_rclk,
8 reg [AWIDTH-1:0] wr_addr, rd_addr;
9 wire [AWIDTH-1:0] wr_addr_rclk, rd_addr_wclk;
10 wire [AWIDTH-1:0] next_rd_addr;
13 // Write side management
14 wire [AWIDTH-1:0] next_wr_addr = wr_addr + 1;
15 always @(posedge wclk or posedge arst)
19 wr_addr <= next_wr_addr;
20 assign full = (next_wr_addr == rd_addr_wclk);
22 // RAM for data storage. Data out is registered, complicating the
24 ram_2port #(.DWIDTH(DWIDTH),.AWIDTH(AWIDTH)) mac_rx_ff_ram
25 (.clka(wclk),.ena(1'b1),.wea(write),.addra(wr_addr),.dia(datain),.doa(),
26 .clkb(rclk),.enb(enb_read),.web(1'b0),.addrb(next_rd_addr),.dib(0),.dob(dataout) );
28 // Read side management
30 assign empty = ~data_valid;
31 assign next_rd_addr = rd_addr + data_valid;
32 assign enb_read = read | ~data_valid;
34 always @(posedge rclk or posedge arst)
38 rd_addr <= rd_addr + 1;
40 always @(posedge rclk or posedge arst)
44 if(read & (next_rd_addr == wr_addr_rclk))
46 else if(next_rd_addr != wr_addr_rclk)
49 // Send pointers across clock domains via gray code
50 gray_send #(.WIDTH(AWIDTH)) send_wr_addr
51 (.clk_in(wclk),.addr_in(wr_addr),
52 .clk_out(rclk),.addr_out(wr_addr_rclk) );
54 gray_send #(.WIDTH(AWIDTH)) send_rd_addr
55 (.clk_in(rclk),.addr_in(rd_addr),
56 .clk_out(wclk),.addr_out(rd_addr_wclk) );
58 // Generate fullness info, these are approximate and may be delayed
59 // and are only for higher-level flow control.
60 // Only full and empty are guaranteed exact.
61 always @(posedge wclk)
62 level_wclk <= wr_addr - rd_addr_wclk;
63 always @(posedge rclk)
64 level_rclk <= wr_addr_rclk - rd_addr;
66 endmodule // fifo_2clock