Merge branch 'grc' from http://gnuradio.org/git/jblum.git into master
[debian/gnuradio] / usrp2 / fpga / serdes / serdes_tb.v
1
2 // FIXME need to add flow control
3
4 module serdes_tb();
5    
6    reg clk, rst;
7    wire ser_rx_clk, ser_tx_clk;
8    wire ser_rklsb, ser_rkmsb, ser_tklsb, ser_tkmsb;
9    wire [15:0] ser_r, ser_t;
10    
11    initial clk = 0;
12    initial rst = 1;
13    initial #1000 rst = 0;
14    always #100 clk = ~clk;
15    
16    // Wishbone
17    reg [31:0]  wb_dat_i;
18    wire [31:0] wb_dat_o_rx, wb_dat_o_tx;
19    reg         wb_we, wb_en_rx, wb_en_tx;
20    reg [8:0]   wb_adr;
21
22    // Buffer Control
23    reg         go, clear, read, write;
24    reg [3:0]   buf_num;
25    wire [31:0] ctrl_word = {buf_num,3'b0,clear,write,read,step,lastline,firstline};
26    reg [8:0]   firstline = 0, lastline = 0;
27    reg [3:0]   step = 1;
28    reg         first_tx = 1, first_rx = 1;  // for verif
29    
30    // TX Side
31    reg         wb_we_tx;
32    wire        en_tx, we_tx;
33    wire [8:0]  addr_tx;
34    wire [31:0] f2r_tx, r2f_tx;
35    wire [31:0] data_tx;
36    wire        read_tx, done_tx, error_tx, sop_tx, eop_tx;
37    
38    wire        fdone_tx, ferror_tx;
39    
40    reg         even;
41    reg         channel_error = 0;
42    
43    serdes_tx serdes_tx
44      (.clk(clk),.rst(rst),
45       .ser_tx_clk(ser_tx_clk),.ser_t(ser_t),.ser_tklsb(ser_tklsb),.ser_tkmsb(ser_tkmsb),
46       .rd_dat_i(data_tx),.rd_read_o(read_tx),.rd_done_o(done_tx),
47       .rd_error_o(error_tx),.rd_sop_i(sop_tx),.rd_eop_i(eop_tx) );
48    
49    ram_2port #(.DWIDTH(32),.AWIDTH(9))
50      ram_tx(.clka(clk),.ena(wb_en_tx),.wea(wb_we_tx),.addra(wb_adr),.dia(wb_dat_i),.doa(wb_dat_o_tx),
51             .clkb(clk),.enb(en_tx),.web(we_tx),.addrb(addr_tx),.dib(f2r_tx),.dob(r2f_tx));
52    
53    buffer_int #(.BUFF_NUM(1)) buffer_int_tx
54      (.clk(clk),.rst(rst),
55       .ctrl_word(ctrl_word),.go(go),
56       .done(fdone_tx),.error(ferror_tx),
57       
58       .en_o(en_tx),.we_o(we_tx),.addr_o(addr_tx),.dat_to_buf(f2r_tx),.dat_from_buf(r2f_tx),
59       
60       .wr_dat_i(0),.wr_write_i(0),.wr_done_i(0),
61       .wr_error_i(0),.wr_ready_o(),.wr_full_o(),
62       
63       .rd_dat_o(data_tx),.rd_read_i(read_tx),.rd_done_i(done_tx),
64       .rd_error_i(error_tx),.rd_sop_o(sop_tx),.rd_eop_o(eop_tx) );
65
66
67    // RX Side
68    reg         wb_we_rx;
69    wire        en_rx, we_rx;
70    wire [8:0]  addr_rx;
71    wire [31:0] f2r_rx, r2f_rx;
72    wire [31:0] data_rx;
73    wire        write_rx, done_rx, error_rx, ready_rx, empty_rx;
74    
75    wire        fdone_rx, ferror_rx;
76    
77    serdes_rx serdes_rx
78      (.clk(clk),.rst(rst),
79       .ser_rx_clk(ser_rx_clk),.ser_r(ser_r),.ser_rklsb(ser_rklsb),.ser_rkmsb(ser_rkmsb),
80       .wr_dat_o(data_rx),.wr_write_o(write_rx),.wr_done_o(done_rx),
81       .wr_error_o(error_rx),.wr_ready_i(ready_rx),.wr_full_i(full_rx) );
82
83    ram_2port #(.DWIDTH(32),.AWIDTH(9))
84      ram_rx(.clka(clk),.ena(wb_en_rx),.wea(wb_we_rx),.addra(wb_adr),.dia(wb_dat_i),.doa(wb_dat_o_rx),
85             .clkb(clk),.enb(en_rx),.web(we_rx),.addrb(addr_rx),.dib(f2r_rx),.dob(r2f_rx) );
86    
87    buffer_int #(.BUFF_NUM(0)) buffer_int_rx
88      (.clk(clk),.rst(rst),
89       .ctrl_word(ctrl_word),.go(go),
90       .done(fdone_rx),.error(ferror_rx),
91       
92       .en_o(en_rx),.we_o(we_rx),.addr_o(addr_rx),.dat_to_buf(f2r_rx),.dat_from_buf(r2f_rx),
93       
94       .wr_dat_i(data_rx),.wr_write_i(write_rx),.wr_done_i(done_rx),
95       .wr_error_i(error_rx),.wr_ready_o(ready_rx),.wr_full_o(full_rx),
96       
97       .rd_dat_o(),.rd_read_i(0),.rd_done_i(0),
98       .rd_error_i(0),.rd_sop_o(),.rd_eop_o() );
99
100    // Simulate the connection
101    serdes_model serdes_model
102      (.ser_tx_clk(ser_tx_clk), .ser_tkmsb(ser_tkmsb), .ser_tklsb(ser_tklsb), .ser_t(ser_t),
103       .ser_rx_clk(ser_rx_clk), .ser_rkmsb(ser_rkmsb), .ser_rklsb(ser_rklsb), .ser_r(ser_r),
104       .even(even), .error(channel_error) );
105    
106    initial begin
107       wb_en_rx <= 0;
108       wb_en_tx <=0;
109       wb_we_tx <= 0;
110       wb_we_rx <= 0;
111       wb_adr <= 0;
112       wb_dat_i <= 0;
113       go <= 0;
114       even <= 0;
115       @(negedge rst);
116       @(posedge clk);
117       FillTXRAM;
118       ClearRXRAM;
119       ResetBuffer(0);
120       ResetBuffer(1);
121
122       // receive a full buffer
123       ReceiveSERDES(0,10);
124       SendSERDES(0,10);
125
126       // Receive a partial buffer
127       SendSERDES(11,20);
128       ReceiveSERDES(11,50);
129
130       // Receive too many for buffer
131       SendSERDES(21,100);
132       ReceiveSERDES(21,30);
133
134       // Send 3 packets, then wait to receive them, so they stack up in the rx fifo
135       SendSERDES(31,40);
136       SendSERDES(41,50);
137       SendSERDES(51,60);
138       repeat (10)
139         @(posedge clk);
140       ReceiveSERDES(31,40);
141       ReceiveSERDES(41,50);
142       repeat (1000)
143         @(posedge clk);
144       ReceiveSERDES(51,60);
145
146       // Overfill the FIFO, should get an error on 3rd packet
147       SendSERDES(1,400);
148       SendSERDES(1,400);
149       
150       
151       WaitForTX;
152       //WaitForRX;
153       
154
155       repeat(1000)
156         @(posedge clk);
157       ReceiveSERDES(101,500);
158       ReceiveSERDES(101,500);
159       ReadRAM(80);
160       $finish;
161    end // initial begin
162
163    always @(posedge clk)
164      if(write_rx)
165        $display("SERDES RX, FIFO WRITE %x, FIFO RDY %d, FIFO FULL %d",data_rx, ready_rx, full_rx);
166    
167    always @(posedge clk)
168      if(read_tx)
169        $display("SERDES TX, FIFO READ %x, SOP %d, EOP %d",data_tx, sop_tx, eop_tx);
170    
171    initial begin
172       $dumpfile("serdes_tb.vcd");
173       $dumpvars(0,serdes_tb);
174    end
175
176    initial #10000000 $finish;
177
178    initial #259300 channel_error <= 1;
179    initial #259500 channel_error <= 0;
180    
181    task FillTXRAM;
182       begin
183          wb_adr <= 0;
184          wb_dat_i <= 32'h10802000;
185          wb_we_tx <= 1;
186          wb_en_tx <= 1;
187          @(posedge clk);
188          repeat(511) begin
189             wb_dat_i <= wb_dat_i + 32'h00010001;
190             wb_adr <= wb_adr + 1;
191             @(posedge clk);
192          end // repeat (511)
193          wb_we_tx <= 0;
194          wb_en_tx <= 0;
195          @(posedge clk);
196          $display("Done entering Data into TX RAM\n");
197       end
198    endtask // FillTXRAM
199    
200    task ClearRXRAM;
201       begin
202          wb_adr <= 0;
203          wb_dat_i <= 0;
204          wb_we_rx <= 1;
205          wb_en_rx <= 1;
206          wb_dat_i <= 0;
207          @(posedge clk);
208          repeat(511) begin
209             wb_adr <= wb_adr + 1;
210             @(posedge clk);
211          end // repeat (511)
212          wb_we_rx <= 0;
213          wb_en_rx <= 0;
214          @(posedge clk);
215          $display("Done clearing RX RAM\n");
216       end
217    endtask // FillRAM
218    
219    task ReadRAM;
220       input [8:0] lastline;
221       begin
222          wb_en_rx <= 1;
223          wb_adr <= 0;
224          @(posedge clk);
225          @(posedge clk);
226          repeat(lastline) begin
227             $display("ADDR: %h  DATA %h", wb_adr, wb_dat_o_rx);
228             wb_adr <= wb_adr + 1;
229             @(posedge clk);
230             @(posedge clk);
231          end // repeat (511)
232          $display("ADDR: %h  DATA %h", wb_adr, wb_dat_o_rx);
233          wb_en_rx <= 0;
234          @(posedge clk);
235          $display("Done reading out RX RAM\n");
236       end
237    endtask // FillRAM
238    
239    task ResetBuffer;
240       input [3:0] buffer_num;
241       begin
242          buf_num <= buffer_num;
243          clear <= 1; read <= 0; write <= 0;
244          go <= 1;
245          @(posedge clk);
246          go <= 0;
247          @(posedge clk);
248          $display("Buffer Reset");
249       end
250    endtask // ClearBuffer
251    
252    task SetBufferWrite;
253       input [3:0] buffer_num;
254       input [8:0] start;
255       input [8:0] stop;
256       begin
257          buf_num <= buffer_num;
258          clear <= 0; read <= 0; write <= 1;
259          firstline <= start;
260          lastline <= stop;
261          go <= 1;
262          @(posedge clk);
263          go <= 0;
264          @(posedge clk);
265          $display("Buffer Set for Write");
266       end
267    endtask // SetBufferWrite
268    
269    task SetBufferRead;
270       input [3:0] buffer_num;
271       input [8:0] start;
272       input [8:0] stop;
273       begin
274          buf_num <= buffer_num;
275          clear <= 0; read <= 1; write <= 0;
276          firstline <= start;
277          lastline <= stop;
278          go <= 1;
279          @(posedge clk);
280          go <= 0;
281          @(posedge clk);
282          $display("Buffer Set for Read");
283       end
284    endtask // SetBufferRead
285
286    task WaitForTX;
287       begin
288          while (!(fdone_tx | ferror_tx))
289            @(posedge clk);
290       end
291    endtask // WaitForTX
292    
293    task WaitForRX;
294       begin
295          while (!(fdone_rx | ferror_rx))
296            @(posedge clk);
297       end
298    endtask // WaitForRX
299    
300    task SendSERDES;
301       input [8:0] start;
302       input [8:0] stop;
303       begin
304          if(~first_tx)
305            WaitForTX;
306          else
307            first_tx <= 0;
308          ResetBuffer(1);
309          SetBufferRead(1,start,stop);
310          $display("Here");
311       end
312    endtask // SendSERDES
313    
314    task ReceiveSERDES;
315       input [8:0] start;
316       input [8:0] stop;
317       begin
318          if(~first_rx)
319            WaitForRX;
320          else
321            first_rx <= 0;
322          ResetBuffer(0);
323          SetBufferWrite(0,start,stop);
324          $display("Here2");
325       end
326    endtask // ReceiveSERDES
327    
328 endmodule // serdes_tb