⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tb_spi_top.v

📁 SPI 总线协议源码SPI 总线协议源码SPI 总线协议源码
💻 V
字号:
`include "timescale.v"

module tb_spi_top();

  reg         clk;
  reg         rst;
  wire [31:0] adr;
  wire [31:0] dat_i, dat_o;
  wire        we;
  wire  [3:0] sel;
  wire        stb;
  wire        cyc;
  wire        ack;
  wire        err;
  wire        int;

  wire  [7:0] ss;
  wire        sclk;
  wire        mosi;
  wire        miso;

  reg  [31:0] q;
  reg  [31:0] q1;
  reg  [31:0] q2;
  reg  [31:0] q3;
  reg  [31:0] result;

  parameter SPI_RX_0   = 5'h0;
  parameter SPI_RX_1   = 5'h4;
  parameter SPI_RX_2   = 5'h8;
  parameter SPI_RX_3   = 5'hc;
  parameter SPI_TX_0   = 5'h0;
  parameter SPI_TX_1   = 5'h4;
  parameter SPI_TX_2   = 5'h8;
  parameter SPI_TX_3   = 5'hc;
  parameter SPI_CTRL   = 5'h10;
  parameter SPI_DIVIDE = 5'h14;
  parameter SPI_SS     = 5'h18;

  // Generate clock
  always #5 clk = ~clk;

  // Wishbone master model
  wb_master_model #(32, 32) i_wb_master (
    .clk(clk), .rst(rst),
    .adr(adr), .din(dat_i), .dout(dat_o),
    .cyc(cyc), .stb(stb), .we(we), .sel(sel), .ack(ack), .err(err), .rty(1'b0)
  );

  // SPI master core
  spi_top i_spi_top (
    .wb_clk_i(clk), .wb_rst_i(rst), 
    .wb_adr_i(adr[4:0]), .wb_dat_i(dat_o), .wb_dat_o(dat_i), 
    .wb_sel_i(sel), .wb_we_i(we), .wb_stb_i(stb), 
    .wb_cyc_i(cyc), .wb_ack_o(ack), .wb_err_o(err), .wb_int_o(int),
    .ss_pad_o(ss), .sclk_pad_o(sclk), .mosi_pad_o(mosi), .miso_pad_i(miso) 
  );

  // SPI slave model
  spi_slave_model i_spi_slave (
    .rst(rst), .ss(ss[0]), .sclk(sclk), .mosi(mosi), .miso(miso)
  );

  initial
    begin
      $display("\nstatus: %t Testbench started\n\n", $time);

      $dumpfile("bench.vcd");
      $dumpvars(1, tb_spi_top);
      $dumpvars(1, tb_spi_top.i_spi_slave);

      clk = 0;

      i_spi_slave.rx_negedge = 1'b0;
      i_spi_slave.tx_negedge = 1'b0;

      result = 32'h0;

      rst = 1'b0; 
      #2;
      rst = 1'b1; 
      repeat(20) @(posedge clk);
      rst = 1'b0; 

      $display("status: %t done reset", $time);
      
      @(posedge clk);

      // Program core
      i_wb_master.wb_write(0, SPI_DIVIDE, 32'h00); 
      i_wb_master.wb_write(0, SPI_TX_0, 32'h5a);   
      i_wb_master.wb_write(0, SPI_CTRL, 32'h208);   
      i_wb_master.wb_write(0, SPI_SS, 32'h01);     

      $display("status: %t programmed registers", $time);

      i_wb_master.wb_cmp(0, SPI_DIVIDE, 32'h00);   
      i_wb_master.wb_cmp(0, SPI_TX_0, 32'h5a);     
      i_wb_master.wb_cmp(0, SPI_CTRL, 32'h208);    
      i_wb_master.wb_cmp(0, SPI_SS, 32'h01);       

      $display("status: %t verified registers", $time);

      i_spi_slave.rx_negedge = 1'b1;
      i_spi_slave.tx_negedge = 1'b0;
      i_spi_slave.data[31:0] = 32'ha5967e5a;
      i_wb_master.wb_write(0, SPI_CTRL, 32'h308);   

      $display("status: %t generate transfer:  8 bit, msb first, tx posedge, rx negedge", $time);

      // Check bsy bit
      i_wb_master.wb_read(0, SPI_CTRL, q);
      while (q[8])
        i_wb_master.wb_read(1, SPI_CTRL, q);

      i_wb_master.wb_read(1, SPI_RX_0, q);
      result = result + q;

      if (i_spi_slave.data[7:0] == 8'h5a && q == 32'h000000a5)
        $display("status: %t transfer completed: ok", $time);
      else
        $display("status: %t transfer completed: nok", $time);

      i_spi_slave.rx_negedge = 1'b0;
      i_spi_slave.tx_negedge = 1'b1;
      i_wb_master.wb_write(0, SPI_TX_0, 32'ha5);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h408);   
      i_wb_master.wb_write(0, SPI_CTRL, 32'h508);  

      $display("status: %t generate transfer:  8 bit, msb first, tx negedge, rx posedge", $time);

      // Check bsy bit
      i_wb_master.wb_read(0, SPI_CTRL, q);
      while (q[8])
        i_wb_master.wb_read(1, SPI_CTRL, q);

      i_wb_master.wb_read(1, SPI_RX_0, q);
      result = result + q;

      if (i_spi_slave.data[7:0] == 8'ha5 && q == 32'h00000096)
        $display("status: %t transfer completed: ok", $time);
      else
        $display("status: %t transfer completed: nok", $time);

      i_spi_slave.rx_negedge = 1'b0;
      i_spi_slave.tx_negedge = 1'b1;
      i_wb_master.wb_write(0, SPI_TX_0, 32'h5aa5);
      i_wb_master.wb_write(0, SPI_CTRL, 32'hc10);   
      i_wb_master.wb_write(0, SPI_CTRL, 32'hd10);  

      $display("status: %t generate transfer: 16 bit, lsb first, tx negedge, rx posedge", $time);

      i_wb_master.wb_read(0, SPI_CTRL, q);
      while (q[8])
        i_wb_master.wb_read(1, SPI_CTRL, q);

      i_wb_master.wb_read(1, SPI_RX_0, q);
      result = result + q;

      if (i_spi_slave.data[15:0] == 16'ha55a && q == 32'h00005a7e)
        $display("status: %t transfer completed: ok", $time);
      else
        $display("status: %t transfer completed: nok", $time);

      i_spi_slave.rx_negedge = 1'b1;
      i_spi_slave.tx_negedge = 1'b0;
      i_wb_master.wb_write(0, SPI_TX_0, 32'h76543210);
      i_wb_master.wb_write(0, SPI_TX_1, 32'hfedcba98);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h1a40);   
      i_wb_master.wb_write(0, SPI_CTRL, 32'h1b40);   

      $display("status: %t generate transfer: 64 bit, lsb first, tx posedge, rx negedge", $time);

      // Check bsy bit
      i_wb_master.wb_read(0, SPI_CTRL, q);
      while (q[8])
        i_wb_master.wb_read(1, SPI_CTRL, q);

      i_wb_master.wb_read(1, SPI_RX_0, q);
      result = result + q;
      i_wb_master.wb_read(1, SPI_RX_1, q1);
      result = result + q1;

      if (i_spi_slave.data == 32'h195d3b7f && q == 32'h5aa5a55a && q1 == 32'h76543210)
        $display("status: %t transfer completed: ok", $time);
      else
        $display("status: %t transfer completed: nok", $time);

      i_spi_slave.rx_negedge = 1'b0;
      i_spi_slave.tx_negedge = 1'b1;
      i_wb_master.wb_write(0, SPI_TX_0, 32'hccddeeff);
      i_wb_master.wb_write(0, SPI_TX_1, 32'h8899aabb);
      i_wb_master.wb_write(0, SPI_TX_2, 32'h44556677);
      i_wb_master.wb_write(0, SPI_TX_3, 32'h00112233);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h400);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h500);

      $display("status: %t generate transfer: 128 bit, msb first, tx posedge, rx negedge", $time);

      // Check bsy bit
      i_wb_master.wb_read(0, SPI_CTRL, q);
      while (q[8])
        i_wb_master.wb_read(1, SPI_CTRL, q);

      i_wb_master.wb_read(1, SPI_RX_0, q);
      result = result + q;
      i_wb_master.wb_read(1, SPI_RX_1, q1);
      result = result + q1;
      i_wb_master.wb_read(1, SPI_RX_2, q2);
      result = result + q2;
      i_wb_master.wb_read(1, SPI_RX_3, q3);
      result = result + q3;

      if (i_spi_slave.data == 32'hccddeeff && q == 32'h8899aabb && q1 == 32'h44556677 && q2 == 32'h00112233 && q3 == 32'h195d3b7f)
        $display("status: %t transfer completed: ok", $time);
      else
        $display("status: %t transfer completed: nok", $time);

      i_spi_slave.rx_negedge = 1'b0;
      i_spi_slave.tx_negedge = 1'b1;
      i_wb_master.wb_write(0, SPI_TX_0, 32'haa55a5a5);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h1420);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h1520);

      $display("status: %t generate transfer: 32 bit, msb first, tx negedge, rx posedge, ie", $time);

      // Check interrupt signal
      while (!int)
        @(posedge clk);

      i_wb_master.wb_read(1, SPI_RX_0, q);
      result = result + q;
    
      @(posedge clk);
      if (!int && i_spi_slave.data == 32'haa55a5a5 && q == 32'hccddeeff)
        $display("status: %t transfer completed: ok", $time);
      else
        $display("status: %t transfer completed: nok", $time);

      i_spi_slave.rx_negedge = 1'b1;
      i_spi_slave.tx_negedge = 1'b0;
      i_wb_master.wb_write(0, SPI_TX_0, 32'h01248421);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h3220);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h3320);

      $display("status: %t generate transfer: 32 bit, msb first, tx posedge, rx negedge, ie, ass", $time);

      while (!int)
        @(posedge clk);

      i_wb_master.wb_read(1, SPI_RX_0, q);
      result = result + q;

      @(posedge clk);
      if (!int && i_spi_slave.data == 32'h01248421 && q == 32'haa55a5a5)
        $display("status: %t transfer completed: ok", $time);
      else
        $display("status: %t transfer completed: nok", $time);

      i_spi_slave.rx_negedge = 1'b1;
      i_spi_slave.tx_negedge = 1'b0;
      i_wb_master.wb_write(0, SPI_TX_0, 32'h1);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h3201);
      i_wb_master.wb_write(0, SPI_CTRL, 32'h3301);

      $display("status: %t generate transfer: 1 bit, msb first, tx posedge, rx negedge, ie, ass", $time);

      while (!int)
        @(posedge clk);

      i_wb_master.wb_read(1, SPI_RX_0, q);
      result = result + q;

      @(posedge clk);
      if (!int && i_spi_slave.data == 32'h02490843 && q == 32'h0)
        $display("status: %t transfer completed: ok", $time);
      else
        $display("status: %t transfer completed: nok", $time);

      $display("\n\nstatus: %t Testbench done", $time);

      #25000; // wait 25us

      $display("report (%h)", (result ^ 32'h2e8b36ab) + 32'hdeaddead);
      $display("exit (%h)", result ^ 32'h2e8b36ab);

      $stop;
    end

endmodule


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -