new fifos copied over from other project
[debian/gnuradio] / usrp2 / fpga / control_lib / fifo_2clock.v
1
2 module fifo_2clock
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,
6      input arst);
7
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;
11    wire             enb_read;
12    
13    // Write side management
14    wire [AWIDTH-1:0] next_wr_addr = wr_addr + 1;
15    always @(posedge wclk or posedge arst)
16      if(arst)
17        wr_addr <= 0;
18      else if(write)
19        wr_addr <= next_wr_addr;
20    assign           full = (next_wr_addr == rd_addr_wclk);
21
22    //  RAM for data storage.  Data out is registered, complicating the
23    //     read side logic
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) );
27
28    // Read side management
29    reg              data_valid;
30    assign           empty = ~data_valid;
31    assign           next_rd_addr = rd_addr + data_valid;
32    assign           enb_read = read | ~data_valid;
33
34    always @(posedge rclk or posedge arst)
35      if(arst)
36        rd_addr <= 0;
37      else if(read)
38        rd_addr <= rd_addr + 1;
39
40    always @(posedge rclk or posedge arst)
41      if(arst)
42        data_valid <= 0;
43      else
44        if(read & (next_rd_addr == wr_addr_rclk))
45          data_valid <= 0;
46        else if(next_rd_addr != wr_addr_rclk)
47          data_valid <= 1;
48          
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) );
53    
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) );
57
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;
65    
66 endmodule // fifo_2clock