root / usrp2 / fpga / opencores / i2c / bench / verilog / tst_bench_top.v @ e0fcbaee
History | View | Annotate | Download (14.2 kB)
| 1 | ///////////////////////////////////////////////////////////////////// |
|---|---|
| 2 | //// //// |
| 3 | //// WISHBONE rev.B2 compliant I2C Master controller Testbench //// |
| 4 | //// //// |
| 5 | //// //// |
| 6 | //// Author: Richard Herveille //// |
| 7 | //// [email protected] //// |
| 8 | //// www.asics.ws //// |
| 9 | //// //// |
| 10 | //// Downloaded from: http://www.opencores.org/projects/i2c/ //// |
| 11 | //// //// |
| 12 | ///////////////////////////////////////////////////////////////////// |
| 13 | //// //// |
| 14 | //// Copyright (C) 2001 Richard Herveille //// |
| 15 | //// [email protected] //// |
| 16 | //// //// |
| 17 | //// This source file may be used and distributed without //// |
| 18 | //// restriction provided that this copyright statement is not //// |
| 19 | //// removed from the file and that any derivative work contains //// |
| 20 | //// the original copyright notice and the associated disclaimer.//// |
| 21 | //// //// |
| 22 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
| 23 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
| 24 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
| 25 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
| 26 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
| 27 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
| 28 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
| 29 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
| 30 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
| 31 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
| 32 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
| 33 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
| 34 | //// POSSIBILITY OF SUCH DAMAGE. //// |
| 35 | //// //// |
| 36 | ///////////////////////////////////////////////////////////////////// |
| 37 | |
| 38 | // CVS Log |
| 39 | // |
| 40 | // $Id: tst_bench_top.v,v 1.8 2006/09/04 09:08:51 rherveille Exp $ |
| 41 | // |
| 42 | // $Date: 2006/09/04 09:08:51 $ |
| 43 | // $Revision: 1.8 $ |
| 44 | // $Author: rherveille $ |
| 45 | // $Locker: $ |
| 46 | // $State: Exp $ |
| 47 | // |
| 48 | // Change History: |
| 49 | // $Log: tst_bench_top.v,v $ |
| 50 | // Revision 1.8 2006/09/04 09:08:51 rherveille |
| 51 | // fixed (n)ack generation |
| 52 | // |
| 53 | // Revision 1.7 2005/02/27 09:24:18 rherveille |
| 54 | // Fixed scl, sda delay. |
| 55 | // |
| 56 | // Revision 1.6 2004/02/28 15:40:42 rherveille |
| 57 | // *** empty log message *** |
| 58 | // |
| 59 | // Revision 1.4 2003/12/05 11:04:38 rherveille |
| 60 | // Added slave address configurability |
| 61 | // |
| 62 | // Revision 1.3 2002/10/30 18:11:06 rherveille |
| 63 | // Added timing tests to i2c_model. |
| 64 | // Updated testbench. |
| 65 | // |
| 66 | // Revision 1.2 2002/03/17 10:26:38 rherveille |
| 67 | // Fixed some race conditions in the i2c-slave model. |
| 68 | // Added debug information. |
| 69 | // Added headers. |
| 70 | // |
| 71 | |
| 72 | `include "timescale.v" |
| 73 | |
| 74 | module tst_bench_top(); |
| 75 | |
| 76 | // |
| 77 | // wires && regs |
| 78 | // |
| 79 | reg clk; |
| 80 | reg rstn; |
| 81 | |
| 82 | wire [31:0] adr; |
| 83 | wire [ 7:0] dat_i, dat_o, dat0_i, dat1_i; |
| 84 | wire we; |
| 85 | wire stb; |
| 86 | wire cyc; |
| 87 | wire ack; |
| 88 | wire inta; |
| 89 | |
| 90 | reg [7:0] q, qq; |
| 91 | |
| 92 | wire scl, scl0_o, scl0_oen, scl1_o, scl1_oen; |
| 93 | wire sda, sda0_o, sda0_oen, sda1_o, sda1_oen; |
| 94 | |
| 95 | parameter PRER_LO = 3'b000; |
| 96 | parameter PRER_HI = 3'b001; |
| 97 | parameter CTR = 3'b010; |
| 98 | parameter RXR = 3'b011; |
| 99 | parameter TXR = 3'b011; |
| 100 | parameter CR = 3'b100; |
| 101 | parameter SR = 3'b100; |
| 102 | |
| 103 | parameter TXR_R = 3'b101; // undocumented / reserved output |
| 104 | parameter CR_R = 3'b110; // undocumented / reserved output |
| 105 | |
| 106 | parameter RD = 1'b1; |
| 107 | parameter WR = 1'b0; |
| 108 | parameter SADR = 7'b0010_000; |
| 109 | |
| 110 | // |
| 111 | // Module body |
| 112 | // |
| 113 | |
| 114 | // generate clock |
| 115 | always #5 clk = ~clk; |
| 116 | |
| 117 | // hookup wishbone master model |
| 118 | wb_master_model #(8, 32) u0 ( |
| 119 | .clk(clk), |
| 120 | .rst(rstn), |
| 121 | .adr(adr), |
| 122 | .din(dat_i), |
| 123 | .dout(dat_o), |
| 124 | .cyc(cyc), |
| 125 | .stb(stb), |
| 126 | .we(we), |
| 127 | .sel(), |
| 128 | .ack(ack), |
| 129 | .err(1'b0), |
| 130 | .rty(1'b0) |
| 131 | ); |
| 132 | |
| 133 | wire stb0 = stb & ~adr[3]; |
| 134 | wire stb1 = stb & adr[3]; |
| 135 | |
| 136 | assign dat_i = ({{8'd8}{stb0}} & dat0_i) | ({{8'd8}{stb1}} & dat1_i);
|
| 137 | |
| 138 | // hookup wishbone_i2c_master core |
| 139 | i2c_master_top i2c_top ( |
| 140 | |
| 141 | // wishbone interface |
| 142 | .wb_clk_i(clk), |
| 143 | .wb_rst_i(1'b0), |
| 144 | .arst_i(rstn), |
| 145 | .wb_adr_i(adr[2:0]), |
| 146 | .wb_dat_i(dat_o), |
| 147 | .wb_dat_o(dat0_i), |
| 148 | .wb_we_i(we), |
| 149 | .wb_stb_i(stb0), |
| 150 | .wb_cyc_i(cyc), |
| 151 | .wb_ack_o(ack), |
| 152 | .wb_inta_o(inta), |
| 153 | |
| 154 | // i2c signals |
| 155 | .scl_pad_i(scl), |
| 156 | .scl_pad_o(scl0_o), |
| 157 | .scl_padoen_o(scl0_oen), |
| 158 | .sda_pad_i(sda), |
| 159 | .sda_pad_o(sda0_o), |
| 160 | .sda_padoen_o(sda0_oen) |
| 161 | ), |
| 162 | i2c_top2 ( |
| 163 | |
| 164 | // wishbone interface |
| 165 | .wb_clk_i(clk), |
| 166 | .wb_rst_i(1'b0), |
| 167 | .arst_i(rstn), |
| 168 | .wb_adr_i(adr[2:0]), |
| 169 | .wb_dat_i(dat_o), |
| 170 | .wb_dat_o(dat1_i), |
| 171 | .wb_we_i(we), |
| 172 | .wb_stb_i(stb1), |
| 173 | .wb_cyc_i(cyc), |
| 174 | .wb_ack_o(ack), |
| 175 | .wb_inta_o(inta), |
| 176 | |
| 177 | // i2c signals |
| 178 | .scl_pad_i(scl), |
| 179 | .scl_pad_o(scl1_o), |
| 180 | .scl_padoen_o(scl1_oen), |
| 181 | .sda_pad_i(sda), |
| 182 | .sda_pad_o(sda1_o), |
| 183 | .sda_padoen_o(sda1_oen) |
| 184 | ); |
| 185 | |
| 186 | |
| 187 | // hookup i2c slave model |
| 188 | i2c_slave_model #(SADR) i2c_slave ( |
| 189 | .scl(scl), |
| 190 | .sda(sda) |
| 191 | ); |
| 192 | |
| 193 | // create i2c lines |
| 194 | delay m0_scl (scl0_oen ? 1'bz : scl0_o, scl), |
| 195 | m1_scl (scl1_oen ? 1'bz : scl1_o, scl), |
| 196 | m0_sda (sda0_oen ? 1'bz : sda0_o, sda), |
| 197 | m1_sda (sda1_oen ? 1'bz : sda1_o, sda); |
| 198 | |
| 199 | pullup p1(scl); // pullup scl line |
| 200 | pullup p2(sda); // pullup sda line |
| 201 | |
| 202 | initial |
| 203 | begin |
| 204 | `ifdef WAVES |
| 205 | $shm_open("waves");
|
| 206 | $shm_probe("AS",tst_bench_top,"AS");
|
| 207 | $display("INFO: Signal dump enabled ...\n\n");
|
| 208 | `endif |
| 209 | |
| 210 | // force i2c_slave.debug = 1'b1; // enable i2c_slave debug information |
| 211 | force i2c_slave.debug = 1'b0; // disable i2c_slave debug information |
| 212 | |
| 213 | $display("\nstatus: %t Testbench started\n\n", $time);
|
| 214 | |
| 215 | // $dumpfile("bench.vcd");
|
| 216 | // $dumpvars(1, tst_bench_top); |
| 217 | // $dumpvars(1, tst_bench_top.i2c_slave); |
| 218 | |
| 219 | // initially values |
| 220 | clk = 0; |
| 221 | |
| 222 | // reset system |
| 223 | rstn = 1'b1; // negate reset |
| 224 | #2; |
| 225 | rstn = 1'b0; // assert reset |
| 226 | repeat(1) @(posedge clk); |
| 227 | rstn = 1'b1; // negate reset |
| 228 | |
| 229 | $display("status: %t done reset", $time);
|
| 230 | |
| 231 | @(posedge clk); |
| 232 | |
| 233 | // |
| 234 | // program core |
| 235 | // |
| 236 | |
| 237 | // program internal registers |
| 238 | u0.wb_write(1, PRER_LO, 8'hfa); // load prescaler lo-byte |
| 239 | u0.wb_write(1, PRER_LO, 8'hc8); // load prescaler lo-byte |
| 240 | u0.wb_write(1, PRER_HI, 8'h00); // load prescaler hi-byte |
| 241 | $display("status: %t programmed registers", $time);
|
| 242 | |
| 243 | u0.wb_cmp(0, PRER_LO, 8'hc8); // verify prescaler lo-byte |
| 244 | u0.wb_cmp(0, PRER_HI, 8'h00); // verify prescaler hi-byte |
| 245 | $display("status: %t verified registers", $time);
|
| 246 | |
| 247 | u0.wb_write(1, CTR, 8'h80); // enable core |
| 248 | $display("status: %t core enabled", $time);
|
| 249 | |
| 250 | // |
| 251 | // access slave (write) |
| 252 | // |
| 253 | |
| 254 | // drive slave address |
| 255 | u0.wb_write(1, TXR, {SADR,WR} ); // present slave address, set write-bit
|
| 256 | u0.wb_write(0, CR, 8'h90 ); // set command (start, write) |
| 257 | $display("status: %t generate 'start', write cmd %0h (slave address+write)", $time, {SADR,WR} );
|
| 258 | |
| 259 | // check tip bit |
| 260 | u0.wb_read(1, SR, q); |
| 261 | while(q[1]) |
| 262 | u0.wb_read(0, SR, q); // poll it until it is zero |
| 263 | $display("status: %t tip==0", $time);
|
| 264 | |
| 265 | // send memory address |
| 266 | u0.wb_write(1, TXR, 8'h01); // present slave's memory address |
| 267 | u0.wb_write(0, CR, 8'h10); // set command (write) |
| 268 | $display("status: %t write slave memory address 01", $time);
|
| 269 | |
| 270 | // check tip bit |
| 271 | u0.wb_read(1, SR, q); |
| 272 | while(q[1]) |
| 273 | u0.wb_read(0, SR, q); // poll it until it is zero |
| 274 | $display("status: %t tip==0", $time);
|
| 275 | |
| 276 | // send memory contents |
| 277 | u0.wb_write(1, TXR, 8'ha5); // present data |
| 278 | u0.wb_write(0, CR, 8'h10); // set command (write) |
| 279 | $display("status: %t write data a5", $time);
|
| 280 | |
| 281 | while (scl) #1; |
| 282 | force scl= 1'b0; |
| 283 | #100000; |
| 284 | release scl; |
| 285 | |
| 286 | // check tip bit |
| 287 | u0.wb_read(1, SR, q); |
| 288 | while(q[1]) |
| 289 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 290 | $display("status: %t tip==0", $time);
|
| 291 | |
| 292 | // send memory contents for next memory address (auto_inc) |
| 293 | u0.wb_write(1, TXR, 8'h5a); // present data |
| 294 | u0.wb_write(0, CR, 8'h50); // set command (stop, write) |
| 295 | $display("status: %t write next data 5a, generate 'stop'", $time);
|
| 296 | |
| 297 | // check tip bit |
| 298 | u0.wb_read(1, SR, q); |
| 299 | while(q[1]) |
| 300 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 301 | $display("status: %t tip==0", $time);
|
| 302 | |
| 303 | // |
| 304 | // delay |
| 305 | // |
| 306 | // #100000; // wait for 100us. |
| 307 | // $display("status: %t wait 100us", $time);
|
| 308 | |
| 309 | // |
| 310 | // access slave (read) |
| 311 | // |
| 312 | |
| 313 | // drive slave address |
| 314 | u0.wb_write(1, TXR,{SADR,WR} ); // present slave address, set write-bit
|
| 315 | u0.wb_write(0, CR, 8'h90 ); // set command (start, write) |
| 316 | $display("status: %t generate 'start', write cmd %0h (slave address+write)", $time, {SADR,WR} );
|
| 317 | |
| 318 | // check tip bit |
| 319 | u0.wb_read(1, SR, q); |
| 320 | while(q[1]) |
| 321 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 322 | $display("status: %t tip==0", $time);
|
| 323 | |
| 324 | // send memory address |
| 325 | u0.wb_write(1, TXR, 8'h01); // present slave's memory address |
| 326 | u0.wb_write(0, CR, 8'h10); // set command (write) |
| 327 | $display("status: %t write slave address 01", $time);
|
| 328 | |
| 329 | // check tip bit |
| 330 | u0.wb_read(1, SR, q); |
| 331 | while(q[1]) |
| 332 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 333 | $display("status: %t tip==0", $time);
|
| 334 | |
| 335 | // drive slave address |
| 336 | u0.wb_write(1, TXR, {SADR,RD} ); // present slave's address, set read-bit
|
| 337 | u0.wb_write(0, CR, 8'h90 ); // set command (start, write) |
| 338 | $display("status: %t generate 'repeated start', write cmd %0h (slave address+read)", $time, {SADR,RD} );
|
| 339 | |
| 340 | // check tip bit |
| 341 | u0.wb_read(1, SR, q); |
| 342 | while(q[1]) |
| 343 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 344 | $display("status: %t tip==0", $time);
|
| 345 | |
| 346 | // read data from slave |
| 347 | u0.wb_write(1, CR, 8'h20); // set command (read, ack_read) |
| 348 | $display("status: %t read + ack", $time);
|
| 349 | |
| 350 | // check tip bit |
| 351 | u0.wb_read(1, SR, q); |
| 352 | while(q[1]) |
| 353 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 354 | $display("status: %t tip==0", $time);
|
| 355 | |
| 356 | // check data just received |
| 357 | u0.wb_read(1, RXR, qq); |
| 358 | if(qq !== 8'ha5) |
| 359 | $display("\nERROR: Expected a5, received %x at time %t", qq, $time);
|
| 360 | else |
| 361 | $display("status: %t received %x", $time, qq);
|
| 362 | |
| 363 | // read data from slave |
| 364 | u0.wb_write(1, CR, 8'h20); // set command (read, ack_read) |
| 365 | $display("status: %t read + ack", $time);
|
| 366 | |
| 367 | // check tip bit |
| 368 | u0.wb_read(1, SR, q); |
| 369 | while(q[1]) |
| 370 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 371 | $display("status: %t tip==0", $time);
|
| 372 | |
| 373 | // check data just received |
| 374 | u0.wb_read(1, RXR, qq); |
| 375 | if(qq !== 8'h5a) |
| 376 | $display("\nERROR: Expected 5a, received %x at time %t", qq, $time);
|
| 377 | else |
| 378 | $display("status: %t received %x", $time, qq);
|
| 379 | |
| 380 | // read data from slave |
| 381 | u0.wb_write(1, CR, 8'h20); // set command (read, ack_read) |
| 382 | $display("status: %t read + ack", $time);
|
| 383 | |
| 384 | // check tip bit |
| 385 | u0.wb_read(1, SR, q); |
| 386 | while(q[1]) |
| 387 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 388 | $display("status: %t tip==0", $time);
|
| 389 | |
| 390 | // check data just received |
| 391 | u0.wb_read(1, RXR, qq); |
| 392 | $display("status: %t received %x from 3rd read address", $time, qq);
|
| 393 | |
| 394 | // read data from slave |
| 395 | u0.wb_write(1, CR, 8'h28); // set command (read, nack_read) |
| 396 | $display("status: %t read + nack", $time);
|
| 397 | |
| 398 | // check tip bit |
| 399 | u0.wb_read(1, SR, q); |
| 400 | while(q[1]) |
| 401 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 402 | $display("status: %t tip==0", $time);
|
| 403 | |
| 404 | // check data just received |
| 405 | u0.wb_read(1, RXR, qq); |
| 406 | $display("status: %t received %x from 4th read address", $time, qq);
|
| 407 | |
| 408 | // |
| 409 | // check invalid slave memory address |
| 410 | // |
| 411 | |
| 412 | // drive slave address |
| 413 | u0.wb_write(1, TXR, {SADR,WR} ); // present slave address, set write-bit
|
| 414 | u0.wb_write(0, CR, 8'h90 ); // set command (start, write) |
| 415 | $display("status: %t generate 'start', write cmd %0h (slave address+write). Check invalid address", $time, {SADR,WR} );
|
| 416 | |
| 417 | // check tip bit |
| 418 | u0.wb_read(1, SR, q); |
| 419 | while(q[1]) |
| 420 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 421 | $display("status: %t tip==0", $time);
|
| 422 | |
| 423 | // send memory address |
| 424 | u0.wb_write(1, TXR, 8'h10); // present slave's memory address |
| 425 | u0.wb_write(0, CR, 8'h10); // set command (write) |
| 426 | $display("status: %t write slave memory address 10", $time);
|
| 427 | |
| 428 | // check tip bit |
| 429 | u0.wb_read(1, SR, q); |
| 430 | while(q[1]) |
| 431 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 432 | $display("status: %t tip==0", $time);
|
| 433 | |
| 434 | // slave should have send NACK |
| 435 | $display("status: %t Check for nack", $time);
|
| 436 | if(!q[7]) |
| 437 | $display("\nERROR: Expected NACK, received ACK\n");
|
| 438 | |
| 439 | // read data from slave |
| 440 | u0.wb_write(1, CR, 8'h40); // set command (stop) |
| 441 | $display("status: %t generate 'stop'", $time);
|
| 442 | |
| 443 | // check tip bit |
| 444 | u0.wb_read(1, SR, q); |
| 445 | while(q[1]) |
| 446 | u0.wb_read(1, SR, q); // poll it until it is zero |
| 447 | $display("status: %t tip==0", $time);
|
| 448 | |
| 449 | #250000; // wait 250us |
| 450 | $display("\n\nstatus: %t Testbench done", $time);
|
| 451 | $finish; |
| 452 | end |
| 453 | |
| 454 | endmodule |
| 455 | |
| 456 | module delay (in, out); |
| 457 | input in; |
| 458 | output out; |
| 459 | |
| 460 | assign out = in; |
| 461 | |
| 462 | specify |
| 463 | (in => out) = (600,600); |
| 464 | endspecify |
| 465 | endmodule |
| 466 | |
| 467 |