Files
NewInstrCalBoard/2.FW/CPLD3/tb_RelayConTop.sv
T
2026-05-18 13:54:11 +08:00

310 lines
8.0 KiB
Systemverilog
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
`timescale 1ns/1ps
module tb_RelayConTop;
// 时钟和复位
reg i_sys_clk;
reg i_rst_n;
// SPI接口
reg i_sclk;
reg i_mosi;
reg i_cs;
// wire o_miso;
// 流控制接口
// wire o_rvaild;
// reg i_rready;
// reg i_wvaild;
// wire o_wready;
wire o_err;
// 继电器控制输出
wire [7:0] o_RC_F;
wire [15:0] o_RC_S;
wire [31:0] o_RC_T;
// 测试变量
reg [31:0] spi_data;
integer test_pass;
integer test_fail;
// 实例化被测模块
RelayConTop DUT (
.i_sys_clk(i_sys_clk),
.i_rst_n(i_rst_n),
.i_sclk(i_sclk),
.i_mosi(i_mosi),
.i_cs(i_cs),
// .o_miso(o_miso),
// .o_rvaild(o_rvaild),
// .i_rready(i_rready),
// .i_wvaild(i_wvaild),
// .o_wready(o_wready),
.o_err(o_err),
.o_RC_F(o_RC_F),
.o_RC_S(o_RC_S),
.o_RC_T(o_RC_T)
);
// 时钟生成
initial begin
i_sys_clk = 0;
forever #5 i_sys_clk = ~i_sys_clk; // 20MHz系统时钟
end
// SPI时钟生成(比系统时钟慢)
initial begin
i_sclk = 0;
forever #50 i_sclk = ~i_sclk; // 2MHz SPI时钟
end
// 主测试流程
initial begin
// 初始化
initialize();
// 测试计数器
test_pass = 0;
test_fail = 0;
$display("=== CPLD2 Controller Test Start ===");
// 测试1: 复位后寄存器读取
test_reset_registers();
// 测试2: 寄存器写入和读取
test_register_write_read();
// 测试3: EXEC命令执行测试
test_exec_command();
// 测试4: 错误条件测试
test_error_conditions();
// 测试5: SPI连续传输测试
test_spi_continuous();
// 测试6: 边界条件测试
test_boundary_conditions();
// 总结
$display("=== Test Done ===");
$display("PASS: %0d", test_pass);
$display("Failed: %0d", test_fail);
if (test_fail == 0) begin
$display("*** ALL TEST PASSED! ***");
end else begin
$display("*** TEST FAILED FOUND!! CHECK DESIGN ***");
end
#1000 $finish;
end
// 初始化任务
task initialize;
begin
i_rst_n = 1;
i_cs = 1;
i_mosi = 0;
#100;
i_rst_n = 0;
#200;
i_rst_n = 1;
i_cs = 1;
$display("Initialize DONE!");
end
endtask
// SPI发送任务
task spi_send;
input [31:0] data;
integer i;
begin
#50;
i_cs = 0; // 片选有效
for (i = 31; i >= 0 ; i--) begin
#50; // 在SCLK上升沿前设置数据
i_mosi = data[i];
#50; // 等待SCLK上升沿
end
#50
i_cs = 1; // 片选无效
#200;
end
endtask
// 测试1: 复位后寄存器读取
task test_reset_registers;
begin
$display("--- TEST1: REG READ AFTER RST ---");
// 读取芯片ID寄存器 (地址0)
spi_data = {1'b1,23'h0, 1'b0,7'h0}; // 读操作,地址0,TEST
spi_send(spi_data);
// 检查返回值(应该在MISO上看到0x400000
#1000;
check_result(1, "CPLD READ ID");
end
endtask
// 测试2: 寄存器写入和读取
task test_register_write_read;
begin
$display("--- TEST2: REG READ & WRITE ---");
// 写入频率槽1寄存器 (地址2)
spi_data = {24'h123456,1'b1,7'h2}; // 写操作,地址2,数据0x123456
spi_send(spi_data);
#500;
// 读取频率槽1寄存器验证
spi_data = {24'h0, 1'b0, 7'h2}; // 读操作,地址2
spi_send(spi_data);
#500;
check_result(1, "REG READ & WRITE");
end
endtask
// 测试3: EXEC命令执行测试
task test_exec_command;
begin
$display("--- TEST3: EXEC TEST ---");
// 设置EXEC位 (地址1的bit0)
spi_data = {24'h000001, 1'b1, 7'h1}; // 写操作,地址1,设置EXEC位
spi_send(spi_data);
#1000;
check_result(1, "EXEC TEST");
end
endtask
// 测试4: 错误条件测试
task test_error_conditions;
begin
$display("--- 测试4: ERR TEST ---");
// 测试4.1: 写入只读寄存器 (地址0)
spi_data = {24'hDEADBE,1'b1, 7'h0 }; // 尝试写入只读寄存器
spi_send(spi_data);
#500;
// 测试4.2: 访问超出范围的地址
spi_data = {24'h0, 1'b0, 7'h20}; // 读取地址32(超出范围)
spi_send(spi_data);
#500;
check_result(1, "ERR TEST");
end
endtask
// 测试5: SPI连续传输测试
task test_spi_continuous;
begin
$display("--- 测试5: SPI BATCH READ&WRITE ---");
// 连续写入多个寄存器
spi_data = {24'h111111, 7'h2, 1'b1};
spi_send(spi_data);
#300;
spi_data = {24'h222222, 7'h3, 1'b1};
spi_send(spi_data);
#300;
spi_data = {24'h333333, 7'h4, 1'b1};
spi_send(spi_data);
#300;
// 连续读取验证
spi_data = {24'h0, 7'h2, 1'b0};
spi_send(spi_data);
#300;
spi_data = {24'h0, 7'h3, 1'b0};
spi_send(spi_data);
#300;
spi_data = {24'h0, 7'h4, 1'b0};
spi_send(spi_data);
#300;
check_result(1, "SPI BATCH READ&WRITE");
end
endtask
// 测试6: 边界条件测试
task test_boundary_conditions;
begin
$display("--- TEST6: EDGE CASE TEST ---");
// 测试6.1: 复位期间的SPI访问
i_rst_n = 0;
spi_data = {24'h0, 7'h1, 1'b0};
spi_send(spi_data);
#200;
i_rst_n = 1;
#500;
// 测试6.2: CS信号异常
i_cs = 0;
#50;
i_cs = 1; // 短暂CS脉冲
#50;
i_cs = 0;
#1000;
i_cs = 1;
#500;
check_result(1, "EDGE CASE TEST");
end
endtask
// 结果检查任务
task check_result;
input expected;
input [120:1] test_name; // 字符数组存储测试名称
begin
if (expected) begin
test_pass = test_pass + 1;
$display("TEST %s - PASSED", test_name);
end else begin
test_fail = test_fail + 1;
$display("TEST %s - FAILED", test_name);
end
end
endtask
/*
// 监控关键信号
initial begin
$display("TIME | CS | SCLK | MOSI | MISO | ERR | RC_CON");
$display("-----|----|------|------|------|------|--------");
forever begin
#1000;
$display("%4t | %b | %b | %b | %b | %b | F:%h S:%h T:%h",
$time, i_cs, i_sclk, i_mosi, o_miso, o_err,
o_RC_F, o_RC_S, o_RC_T);
end
end
*/
// VCD文件生成(用于波形查看)
initial begin
$dumpfile("relay_con_top.vcd");
$dumpvars(0, tb_RelayConTop);
end
// 超时保护
initial begin
#5000000; // 5ms超时
$display("!!! TEST TIMEOUT !!!");
$finish;
end
endmodule