Merge branch 'new_eth' of http://gnuradio.org/git/matt into master
[debian/gnuradio] / usrp2 / fpga / control_lib / newfifo / fifo_2clock.v
1
2 // FIXME ignores the AWIDTH (fifo size) parameter
3
4 module fifo_2clock
5   #(parameter WIDTH=36, SIZE=6)
6    (input wclk, input [WIDTH-1:0] datain, input src_rdy_i, output dst_rdy_o, output [15:0] space,
7     input rclk, output [WIDTH-1:0] dataout, output src_rdy_o, input dst_rdy_i, output [15:0] occupied,
8     input arst);
9    
10    wire [SIZE:0] level_rclk, level_wclk; // xilinx adds an extra bit if you ask for accurate levels
11    wire          full, empty, write, read;
12
13    assign dst_rdy_o  = ~full;
14    assign src_rdy_o  = ~empty;
15    assign write      = src_rdy_i & dst_rdy_o;
16    assign read       = src_rdy_o & dst_rdy_i;
17
18    generate
19       if(WIDTH==36)
20         if(SIZE==9)
21           fifo_xlnx_512x36_2clk fifo_xlnx_512x36_2clk
22                (.rst(rst),
23                 .wr_clk(wclk),.din(datain),.full(full),.wr_en(write),.wr_data_count(level_wclk),
24                 .rd_clk(rclk),.dout(dataout),.empty(empty),.rd_en(read),.rd_data_count(level_rclk) );
25         else if(SIZE==11)
26           fifo_xlnx_2Kx36_2clk fifo_xlnx_2Kx36_2clk 
27                      (.rst(rst),
28                       .wr_clk(wclk),.din(datain),.full(full),.wr_en(write),.wr_data_count(level_wclk),
29                       .rd_clk(rclk),.dout(dataout),.empty(empty),.rd_en(read),.rd_data_count(level_rclk) );
30         else if(SIZE==6)
31           fifo_xlnx_64x36_2clk fifo_xlnx_64x36_2clk 
32                      (.rst(rst),
33                       .wr_clk(wclk),.din(datain),.full(full),.wr_en(write),.wr_data_count(level_wclk),
34                       .rd_clk(rclk),.dout(dataout),.empty(empty),.rd_en(read),.rd_data_count(level_rclk) );
35         else
36           fifo_xlnx_512x36_2clk fifo_xlnx_512x36_2clk
37                (.rst(rst),
38                 .wr_clk(wclk),.din(datain),.full(full),.wr_en(write),.wr_data_count(level_wclk),
39                 .rd_clk(rclk),.dout(dataout),.empty(empty),.rd_en(read),.rd_data_count(level_rclk) );
40       else if((WIDTH==19)|(WIDTH==18))
41         if(SIZE==4)
42           fifo_xlnx_16x19_2clk fifo_xlnx_16x19_2clk
43                      (.rst(rst),
44                       .wr_clk(wclk),.din(datain),.full(full),.wr_en(write),.wr_data_count(level_wclk),
45                       .rd_clk(rclk),.dout(dataout),.empty(empty),.rd_en(read),.rd_data_count(level_rclk) );
46    endgenerate
47    
48    assign occupied  = {{(16-SIZE-1){1'b0}},level_rclk};
49    assign space     = ((1<<SIZE)+1)-level_wclk;
50    
51 endmodule // fifo_2clock
52
53 /*
54 `else
55    // ISE sucks, so the following doesn't work properly
56
57    reg [AWIDTH-1:0] wr_addr, rd_addr;
58    wire [AWIDTH-1:0] wr_addr_rclk, rd_addr_wclk;
59    wire [AWIDTH-1:0] next_rd_addr;
60    wire             enb_read;
61    
62    // Write side management
63    wire [AWIDTH-1:0] next_wr_addr = wr_addr + 1;
64    always @(posedge wclk or posedge arst)
65      if(arst)
66        wr_addr <= 0;
67      else if(write)
68        wr_addr <= next_wr_addr;
69    assign           full = (next_wr_addr == rd_addr_wclk);
70
71    //  RAM for data storage.  Data out is registered, complicating the
72    //     read side logic
73    ram_2port #(.DWIDTH(DWIDTH),.AWIDTH(AWIDTH)) mac_rx_ff_ram
74      (.clka(wclk),.ena(1'b1),.wea(write),.addra(wr_addr),.dia(datain),.doa(),
75       .clkb(rclk),.enb(enb_read),.web(1'b0),.addrb(next_rd_addr),.dib(0),.dob(dataout) );
76
77    // Read side management
78    reg              data_valid;
79    assign           empty = ~data_valid;
80    assign           next_rd_addr = rd_addr + data_valid;
81    assign           enb_read = read | ~data_valid;
82
83    always @(posedge rclk or posedge arst)
84      if(arst)
85        rd_addr <= 0;
86      else if(read)
87        rd_addr <= rd_addr + 1;
88
89    always @(posedge rclk or posedge arst)
90      if(arst)
91        data_valid <= 0;
92      else
93        if(read & (next_rd_addr == wr_addr_rclk))
94          data_valid <= 0;
95        else if(next_rd_addr != wr_addr_rclk)
96          data_valid <= 1;
97          
98    // Send pointers across clock domains via gray code
99    gray_send #(.WIDTH(AWIDTH)) send_wr_addr
100      (.clk_in(wclk),.addr_in(wr_addr),
101       .clk_out(rclk),.addr_out(wr_addr_rclk) );
102    
103    gray_send #(.WIDTH(AWIDTH)) send_rd_addr
104      (.clk_in(rclk),.addr_in(rd_addr),
105       .clk_out(wclk),.addr_out(rd_addr_wclk) );
106
107    // Generate fullness info, these are approximate and may be delayed 
108    // and are only for higher-level flow control.  
109    // Only full and empty are guaranteed exact.
110    always @(posedge wclk) 
111      level_wclk <= wr_addr - rd_addr_wclk;
112    always @(posedge rclk) 
113      level_rclk <= wr_addr_rclk - rd_addr;
114 `endif
115 endmodule // fifo_2clock
116
117 */