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

📄 can_testbench.v

📁 人民邮电出版社出版的《FPGA硬件接口设计实践》一书的代码
💻 V
📖 第 1 页 / 共 4 页
字号:

// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
`include "can_defines.v"
`include "can_testbench_defines.v"

module can_testbench();



parameter Tp = 1;
parameter BRP = 2*(`CAN_TIMING0_BRP + 1);


`ifdef CAN_WISHBONE_IF
  reg         wb_clk_i;
  reg         wb_rst_i;
  reg   [7:0] wb_dat_i;
  wire  [7:0] wb_dat_o;
  reg         wb_cyc_i;
  reg         wb_stb_i;
  reg         wb_we_i;
  reg   [7:0] wb_adr_i;
  wire        wb_ack_o;
  reg         wb_free;
`else
  reg         rst_i;
  reg         ale_i;
  reg         rd_i;
  reg         wr_i;
  wire  [7:0] port_0;
  wire  [7:0] port_0_i;
  reg   [7:0] port_0_o;
  reg         port_0_en;
  reg         port_free;
`endif


reg         cs_can;
reg         clk;
reg         rx;
wire        tx;
wire        irq;
wire        clkout;

wire        rx_and_tx;

integer     start_tb;
reg   [7:0] tmp_data;
reg         delayed_tx;
reg         tx_bypassed;
reg         extended_mode;



// Instantiate can_top module
can_top i_can_top
( 
`ifdef CAN_WISHBONE_IF
  .wb_clk_i(wb_clk_i),
  .wb_rst_i(wb_rst_i),
  .wb_dat_i(wb_dat_i),
  .wb_dat_o(wb_dat_o),
  .wb_cyc_i(wb_cyc_i),
  .wb_stb_i(wb_stb_i),
  .wb_we_i(wb_we_i),
  .wb_adr_i(wb_adr_i),
  .wb_ack_o(wb_ack_o),
`else
  .rst_i(rst_i),
  .ale_i(ale_i),
  .rd_i(rd_i),
  .wr_i(wr_i),
  .port_0_io(port_0),
`endif
  .cs_can_i(cs_can),
  .clk_i(clk),
  .rx_i(rx_and_tx),
  .tx_o(tx),
  .irq_on(irq),
  .clkout_o(clkout)
);


`ifdef CAN_WISHBONE_IF
  // Generate wishbone clock signal 10 MHz
  initial
  begin
    wb_clk_i=0;
    forever #50 wb_clk_i = ~wb_clk_i;
  end
`endif


`ifdef CAN_WISHBONE_IF
`else
  assign port_0_i = port_0;
  assign port_0 = port_0_en? port_0_o : 8'hz;
`endif


// Generate clock signal 24 MHz
initial
begin
  clk=0;
  forever #21 clk = ~clk;
end


initial
begin
  start_tb = 0;
  cs_can = 0;
  rx = 1;
  extended_mode = 0;
  tx_bypassed = 0;

  `ifdef CAN_WISHBONE_IF
    wb_dat_i = 'hz;
    wb_cyc_i = 0;
    wb_stb_i = 0;
    wb_we_i = 'hz;
    wb_adr_i = 'hz;
    wb_free = 1;
    wb_rst_i = 1;
    #200 wb_rst_i = 0;
    #200 start_tb = 1;
  `else
    rst_i = 1'b0;
    ale_i = 1'b0;
    rd_i  = 1'b0;
    wr_i  = 1'b0;
    port_0_o = 8'h0;
    port_0_en = 0;
    port_free = 1;
    rst_i = 1;
    #200 rst_i = 0;
    #200 start_tb = 1;
  `endif
end




// Generating delayed tx signal (CAN transciever delay)
always
begin
  wait (tx);
  repeat (4*BRP) @ (posedge clk);   // 4 time quants delay
  #1 delayed_tx = tx;
  wait (~tx);
  repeat (4*BRP) @ (posedge clk);   // 4 time quants delay
  #1 delayed_tx = tx;
end

//assign rx_and_tx = rx & delayed_tx;   FIX ME !!!
assign rx_and_tx = rx & (delayed_tx | tx_bypassed);   // When this signal is on, tx is not looped back to the rx.


// Main testbench
initial
begin
  wait(start_tb);

  // Set bus timing register 0
  write_register(8'd6, {`CAN_TIMING0_SJW, `CAN_TIMING0_BRP});

  // Set bus timing register 1
  write_register(8'd7, {`CAN_TIMING1_SAM, `CAN_TIMING1_TSEG2, `CAN_TIMING1_TSEG1});


  // Set Clock Divider register
  extended_mode = 1'b0;
  write_register(8'd31, {extended_mode, 3'h0, 1'b0, 3'h0});   // Setting the normal mode (not extended)


  // Set Acceptance Code and Acceptance Mask registers (their address differs for basic and extended mode
/*
  // Set Acceptance Code and Acceptance Mask registers
  write_register(8'd16, 8'ha6); // acceptance code 0
  write_register(8'd17, 8'hb0); // acceptance code 1
  write_register(8'd18, 8'h12); // acceptance code 2
  write_register(8'd19, 8'h30); // acceptance code 3
  write_register(8'd20, 8'h0); // acceptance mask 0
  write_register(8'd21, 8'h0); // acceptance mask 1
  write_register(8'd22, 8'h00); // acceptance mask 2
  write_register(8'd23, 8'h00); // acceptance mask 3
*/

  // Set Acceptance Code and Acceptance Mask registers
  write_register(8'd4, 8'he8); // acceptance code
  write_register(8'd5, 8'h0f); // acceptance mask
  
  #10;
  repeat (1000) @ (posedge clk);
  
  // Switch-off reset mode
  write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});

  repeat (BRP) @ (posedge clk);   // At least BRP clocks needed before bus goes to dominant level. Otherwise 1 quant difference is possible
                                  // This difference is resynchronized later.

  // After exiting the reset mode sending bus free
  repeat (11) send_bit(1);

//  test_synchronization;       // test currently switched off
//  test_empty_fifo_ext;        // test currently switched off
//  test_full_fifo_ext;         // test currently switched off
//  send_frame_ext;             // test currently switched off
//  test_empty_fifo;            // test currently switched off
  test_full_fifo;             // test currently switched on
//  send_frame;                 // test currently switched off
//  bus_off_test;               // test currently switched off
//  forced_bus_off;             // test currently switched off
//  send_frame_basic;           // test currently switched off
//  send_frame_extended;        // test currently switched off
//  self_reception_request;       // test currently switched off
//  manual_frame_basic;         // test currently switched off
//  manual_frame_ext;           // test currently switched off

  $display("CAN Testbench finished !");
  $stop;
end


task forced_bus_off;    // Forcing bus-off by writinf to tx_err_cnt register
  begin

    // Switch-on reset mode
    write_register(8'd0, {7'h0, `CAN_MODE_RESET});

    // Set Clock Divider register
    write_register(8'd31, {1'b1, 7'h0});    // Setting the extended mode (not normal)

    // Write 255 to tx_err_cnt register - Forcing bus-off
    write_register(8'd15, 255);

    // Switch-off reset mode
    write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});

//    #1000000;
    #2500000;


    // Switch-on reset mode
    write_register(8'd0, {7'h0, `CAN_MODE_RESET});

    // Write 245 to tx_err_cnt register
    write_register(8'd15, 245);

    // Switch-off reset mode
    write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});

    #1000000;


  end
endtask   // forced_bus_off


task manual_frame_basic;    // Testbench sends a basic format frame
  begin


    // Switch-on reset mode
    write_register(8'd0, {7'h0, (`CAN_MODE_RESET)});
  
    // Set Acceptance Code and Acceptance Mask registers
    write_register(8'd4, 8'h28); // acceptance code
    write_register(8'd5, 8'hff); // acceptance mask
    
    repeat (100) @ (posedge clk);
    
    // Switch-off reset mode
    write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});

    // After exiting the reset mode sending bus free
    repeat (11) send_bit(1);


    write_register(8'd10, 8'h55); // Writing ID[10:3] = 0x55
    write_register(8'd11, 8'h57); // Writing ID[2:0] = 0x2, rtr = 1, length = 7
    write_register(8'd12, 8'h00); // data byte 1
    write_register(8'd13, 8'h00); // data byte 2
    write_register(8'd14, 8'h00); // data byte 3
    write_register(8'd15, 8'h00); // data byte 4
    write_register(8'd16, 8'h00); // data byte 5
    write_register(8'd17, 8'h00); // data byte 6
    write_register(8'd18, 8'h00); // data byte 7
    write_register(8'd19, 8'h00); // data byte 8

    tx_bypassed = 1;    // When this signal is on, tx is not looped back to the rx.
    
    fork
      begin
//        tx_request_command;
        self_reception_request_command;
      end

      begin
        #2200;


        repeat (1)
        begin
          send_bit(0);  // SOF
          send_bit(0);  // ID
          send_bit(1);  // ID
          send_bit(0);  // ID
          send_bit(1);  // ID
          send_bit(0);  // ID
          send_bit(1);  // ID
          send_bit(0);  // ID
          send_bit(1);  // ID
          send_bit(0);  // ID
          send_bit(1);  // ID
          send_bit(0);  // ID
          send_bit(1);  // RTR
          send_bit(0);  // IDE
          send_bit(0);  // r0
          send_bit(0);  // DLC
          send_bit(1);  // DLC
          send_bit(1);  // DLC
          send_bit(1);  // DLC
          send_bit(1);  // CRC
          send_bit(1);  // CRC
          send_bit(0);  // CRC stuff
          send_bit(0);  // CRC 6
          send_bit(0);  // CRC
          send_bit(0);  // CRC
          send_bit(0);  // CRC
          send_bit(1);  // CRC  stuff
          send_bit(0);  // CRC 0
          send_bit(0);  // CRC
          send_bit(1);  // CRC
          send_bit(0);  // CRC
          send_bit(1);  // CRC 5
          send_bit(1);  // CRC
          send_bit(0);  // CRC
          send_bit(1);  // CRC
          send_bit(1);  // CRC b
          send_bit(1);  // CRC DELIM
          send_bit(0);  // ACK
          send_bit(1);  // ACK DELIM
          send_bit(1);  // EOF
          send_bit(1);  // EOF
          send_bit(1);  // EOF
          send_bit(1);  // EOF
          send_bit(1);  // EOF
          send_bit(1);  // EOF
          send_bit(1);  // EOF
          send_bit(1);  // INTER
          send_bit(1);  // INTER
          send_bit(1);  // INTER
        end // repeat



      end
    
    
    join



    read_receive_buffer;
    release_rx_buffer_command;

    read_receive_buffer;
    release_rx_buffer_command;
    read_receive_buffer;

    #4000000;

  end
endtask   //  manual_frame_basic



task manual_frame_ext;    // Testbench sends an extended format frame
  begin


    // Switch-on reset mode
    write_register(8'd0, {7'h0, (`CAN_MODE_RESET)});

    // Set Clock Divider register
    extended_mode = 1'b1;
    write_register(8'd31, {extended_mode, 7'h0});    // Setting the extended mode
  
    // Set Acceptance Code and Acceptance Mask registers
    write_register(8'd16, 8'ha6); // acceptance code 0
    write_register(8'd17, 8'h00); // acceptance code 1
    write_register(8'd18, 8'h5a); // acceptance code 2
    write_register(8'd19, 8'hac); // acceptance code 3
    write_register(8'd20, 8'h00); // acceptance mask 0
    write_register(8'd21, 8'h00); // acceptance mask 1
    write_register(8'd22, 8'h00); // acceptance mask 2
    write_register(8'd23, 8'h00); // acceptance mask 3
    
    repeat (100) @ (posedge clk);
    
    // Switch-off reset mode
    write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});

    // After exiting the reset mode sending bus free
    repeat (11) send_bit(1);


    // Extended frame format
    // Writing TX frame information + identifier + data
    write_register(8'd16, 8'hc5);   // Frame format = 1, Remote transmision request = 1, DLC = 5
    write_register(8'd17, 8'ha6);   // ID[28:21] = a6
    write_register(8'd18, 8'h00);   // ID[20:13] = 00
    write_register(8'd19, 8'h5a);   // ID[12:5]  = 5a
    write_register(8'd20, 8'ha8);   // ID[4:0]   = 15
    // write_register(8'd21, 8'h78); RTR does not send any data
    // write_register(8'd22, 8'h9a);
    // write_register(8'd23, 8'hbc);
    // write_register(8'd24, 8'hde);
    // write_register(8'd25, 8'hf0);
    // write_register(8'd26, 8'h0f);
    // write_register(8'd27, 8'hed);
    // write_register(8'd28, 8'hcb);


    // Enabling IRQ's (extended mode)
    write_register(8'd4, 8'hff);

    // tx_bypassed = 1;    // When this signal is on, tx is not looped back to the rx.
    
    fork
      begin
        tx_request_command;
//        self_reception_request_command;
      end

      begin
        #2400;

        repeat (1)
        begin
          send_bit(0);  // SOF
          send_bit(1);  // ID
          send_bit(0);  // ID
          send_bit(1);  // ID
          send_bit(0);  // ID a
          send_bit(0);  // ID
          send_bit(1);  // ID
          send_bit(1);  // ID
          send_bit(0);  // ID 6
          send_bit(0);  // ID
          send_bit(0);  // ID
          send_bit(0);  // ID 
          send_bit(1);  // RTR
          send_bit(1);  // IDE
          send_bit(0);  // ID 0
          send_bit(0);  // ID 
          send_bit(0);  // ID 
          send_bit(0);  // ID 
          send_bit(0);  // ID 0
          send_bit(1);  // ID stuff
          send_bit(0);  // ID 
          send_bit(1);  // ID 
          send_bit(0);  // ID 
          send_bit(1);  // ID 6
          send_bit(1);  // ID 
          send_bit(0);  // ID 
          send_bit(1);  // ID 
          send_bit(0);  // ID a
          send_bit(1);  // ID 1

⌨️ 快捷键说明

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