Copied wb_1master back from quad radio
[debian/gnuradio] / usrp2 / fpga / eth / rtl / verilog / elastic_buffer.v
1
2
3 module elastic_buffer
4   ( input rx_clk,
5     input tx_clk,
6     input rst,
7     
8     input [7:0] rxd,
9     input       rx_dv,
10     input       rx_er,
11     input       crs,
12     input       col,
13     
14     output [7:0] rxd_ret,
15     output       rx_dv_ret,
16     output       rx_er_ret,
17     output       crs_ret,
18     output       col_ret );
19
20    reg [3:0]     addr_wr,addr_wr_gray,awg_d1,awg_d2,addr_wr_gray_ret,awgr_d1,addr_wr_ungray,addr_rd;
21    
22    reg [11:0]    buffer [0:15];
23    integer       i;
24    initial
25      for(i=0;i<16;i=i+1)
26        buffer[i] <= 0;
27    
28    reg [7:0]     rxd_d1, rxd_d2;
29    reg           rx_dv_d1,rx_er_d1,crs_d1,col_d1, rx_dv_d2,rx_er_d2,crs_d2,col_d2;               
30    wire          rx_dv_ret_adv;
31    reg           rx_dv_ontime;
32
33    always @(posedge rx_clk)
34      {col_d1,crs_d1,rx_er_d1,rx_dv_d1,rxd_d1} <= {col,crs,rx_er,rx_dv,rxd};
35
36    always @(posedge rx_clk)
37      {col_d2,crs_d2,rx_er_d2,rx_dv_d2,rxd_d2} <= {col_d1,crs_d1,rx_er_d1,rx_dv_d1,rxd_d1};
38    
39    always @(posedge rx_clk)
40      buffer[addr_wr] <= {col_d2,crs_d2,rx_er_d2,rx_dv_d1,rxd_d2};
41    
42    always @(posedge rx_clk or posedge rst)
43      if(rst) addr_wr <= 0;
44      else addr_wr <= addr_wr + 1;
45    
46    always @(posedge rx_clk)
47      begin
48         addr_wr_gray <= {addr_wr[3],^addr_wr[3:2],^addr_wr[2:1],^addr_wr[1:0]};
49         awg_d1 <= addr_wr_gray;
50         awg_d2 <= awg_d1;
51      end
52    
53    always @(posedge tx_clk)
54      begin
55         addr_wr_gray_ret <= awg_d2;
56         awgr_d1 <= addr_wr_gray_ret;
57         addr_wr_ungray <= {awgr_d1[3],^awgr_d1[3:2],^awgr_d1[3:1],^awgr_d1[3:0]};
58      end
59
60    wire [3:0] addr_delta = addr_rd-addr_wr_ungray;
61    reg  [1:0] direction;
62    localparam retard = 2'd0;
63    localparam good = 2'd1;
64    localparam advance = 2'd2;
65    localparam wayoff = 2'd3;
66    
67    always @*
68      case(addr_delta)
69        4'd1, 4'd2, 4'd3, 4'd4, 4'd5 : direction <= retard;
70        4'd15, 4'd14, 4'd13, 4'd12, 4'd11 : direction <= advance;
71        4'd0 : direction <= good;
72        default : direction <= wayoff;
73      endcase // case(addr_delta)
74         
75    always @(posedge tx_clk or posedge rst)
76      if(rst)
77        addr_rd <= 0;
78      else if(rx_dv_ret_adv | rx_dv_ontime)
79        addr_rd <= addr_rd + 1;
80      else
81        case(direction)
82          retard : addr_rd <= addr_rd;
83          advance : addr_rd <= addr_rd + 2;
84          good : addr_rd <= addr_rd + 1;
85          wayoff : addr_rd <= addr_wr_ungray;
86        endcase // case(direction)
87    
88    assign     {col_ret,crs_ret,rx_er_ret,rx_dv_ret_adv,rxd_ret} = buffer[addr_rd];
89    always @(posedge tx_clk)
90      rx_dv_ontime <= rx_dv_ret_adv;
91
92    assign        rx_dv_ret = rx_dv_ontime;
93 endmodule // elastic_buffer