310 lines
8.0 KiB
Systemverilog
310 lines
8.0 KiB
Systemverilog
`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 |