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