CAN 总线 通信控制器的 仿真程序,需要模拟数据的发送和接收。下面是测试程序的部分代码:
- //连接 can_top 模块
- can_top i_can_top
- (
- .cs_can_i(cs_can),
- .clk_i(clk),
- .rx_i(rx_and_tx),
- .tx_o(tx),
- .irq_on(irq),
- .clkout_o(clkout)
- );
- //产生 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;
- 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;
- end
- //产生延迟的 tx 信号(CAN 发送器延迟)
- 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 | tx_bypassed); // When this signal is on, tx is notlooped back to the rx.
- //主程序
- initial
- begin
- wait(start_tb);
- //设置总线时序寄存器
- write_register(8'd6, {`CAN_TIMING0_SJW, `CAN_TIMING0_BRP});
- write_register(8'd7, {`CAN_TIMING1_SAM, `CAN_TIMING1_TSEG2, `CAN_TIMING1_TSEG1});
- // 设置时钟分频寄存器
- extended_mode = 1'b0;
- write_register(8'd31, {extended_mode, 3'h0, 1'b0, 3'h0}); // Setting the normal mode (notextended)
- //设置接收代码和接收寄存器
- 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
- write_register(8'd4, 8'he8); // acceptance code
- write_register(8'd5, 8'h0f); // acceptance mask
- #10;
- repeat (1000) @ (posedge clk);
- //开关复位模式
- write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
- repeat (BRP) @ (posedge clk);
- // 在复位后设置总线空闲
- repeat (11) send_bit(1);
- 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
- //切换到复位模式
- write_register(8'd0, {7'h0, `CAN_MODE_RESET});
- // 设置时钟分频寄存器
- write_register(8'd31, {1'b1, 7'h0}); // Setting the extended mode (not normal)
- // 写数据到寄存器中
- write_register(8'd15, 255);
- // 切换复位模式
- write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
- #2500000;
- // 切换复位模式
- write_register(8'd0, {7'h0, `CAN_MODE_RESET});
- // 写数据到寄存器中
- write_register(8'd15, 245);
- //关闭复位模式
- write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
- #1000000;
- end
- endtask // forced_bus_off
复制代码
下面的程序验证如何发送一个基本格式的帧数据:
- //发送一个基本格式的帧
- task manual_frame_basic;
- begin
- // 切换到复位模式
- write_register(8'd0, {7'h0, (`CAN_MODE_RESET)});
- //设置寄存器
- write_register(8'd4, 8'h28); // acceptance code
- write_register(8'd5, 8'hff); // acceptance mask
- repeat (100) @ (posedge clk);
- // 切换复位模式
- write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
- // 模块复位后设置总线空闲
- 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
- self_reception_request_command;
- end
- begin
- #2200;
- repeat (1)
- //开始发送数据
- begin
- send_bit(0); // 帧起始
- 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
复制代码
0
|
|
|
|