179 lines
5.9 KiB
Coq
179 lines
5.9 KiB
Coq
|
|
`timescale 1ns / 1ps
|
|||
|
|
|
|||
|
|
module tb_lvds_1to3_copy_reg;
|
|||
|
|
|
|||
|
|
// 输入信号
|
|||
|
|
reg clk_in_p, clk_in_n;
|
|||
|
|
reg [2:0] data_in_p, data_in_n;
|
|||
|
|
|
|||
|
|
// 输出信号
|
|||
|
|
wire clk_out0_p, clk_out0_n;
|
|||
|
|
wire clk_out1_p, clk_out1_n;
|
|||
|
|
wire clk_out2_p, clk_out2_n;
|
|||
|
|
wire [2:0] data_out0_p, data_out0_n;
|
|||
|
|
wire [2:0] data_out1_p, data_out1_n;
|
|||
|
|
wire [2:0] data_out2_p, data_out2_n;
|
|||
|
|
|
|||
|
|
// 时钟参数
|
|||
|
|
parameter CLK_PERIOD = 10.0; // 100MHz时钟
|
|||
|
|
parameter HALF_PERIOD = CLK_PERIOD / 2;
|
|||
|
|
|
|||
|
|
// 实例化被测试模块
|
|||
|
|
lvds_1to3_copy_reg dut (
|
|||
|
|
.clk_in_p(clk_in_p),
|
|||
|
|
.clk_in_n(clk_in_n),
|
|||
|
|
.data_in_p(data_in_p),
|
|||
|
|
.data_in_n(data_in_n),
|
|||
|
|
.clk_out0_p(clk_out0_p),
|
|||
|
|
.clk_out0_n(clk_out0_n),
|
|||
|
|
.clk_out1_p(clk_out1_p),
|
|||
|
|
.clk_out1_n(clk_out1_n),
|
|||
|
|
.clk_out2_p(clk_out2_p),
|
|||
|
|
.clk_out2_n(clk_out2_n),
|
|||
|
|
.data_out0_p(data_out0_p),
|
|||
|
|
.data_out0_n(data_out0_n),
|
|||
|
|
.data_out1_p(data_out1_p),
|
|||
|
|
.data_out1_n(data_out1_n),
|
|||
|
|
.data_out2_p(data_out2_p),
|
|||
|
|
.data_out2_n(data_out2_n)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// 生成差分时钟信号
|
|||
|
|
always #HALF_PERIOD begin
|
|||
|
|
clk_in_p = ~clk_in_p;
|
|||
|
|
clk_in_n = ~clk_in_p; // 差分信号相位相反
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
// 生成差分数据信号
|
|||
|
|
task generate_diff_data;
|
|||
|
|
input [2:0] data_value;
|
|||
|
|
begin
|
|||
|
|
data_in_p = data_value;
|
|||
|
|
data_in_n = ~data_value; // 差分信号取反
|
|||
|
|
end
|
|||
|
|
endtask
|
|||
|
|
|
|||
|
|
// 检查输出同步性
|
|||
|
|
task check_output_sync;
|
|||
|
|
input integer test_case;
|
|||
|
|
begin
|
|||
|
|
#1; // 等待稳定
|
|||
|
|
|
|||
|
|
// 检查三组输出是否相同
|
|||
|
|
if ((data_out0_p === data_out1_p) &&
|
|||
|
|
(data_out1_p === data_out2_p) &&
|
|||
|
|
(data_out0_n === data_out1_n) &&
|
|||
|
|
(data_out1_n === data_out2_n)) begin
|
|||
|
|
$display("[PASS] Test Case %0d: 三组输出完全同步", test_case);
|
|||
|
|
end else begin
|
|||
|
|
$display("[FAIL] Test Case %0d: 三组输出不同步", test_case);
|
|||
|
|
$display(" Data0_p: %b, Data1_p: %b, Data2_p: %b",
|
|||
|
|
data_out0_p, data_out1_p, data_out2_p);
|
|||
|
|
$display(" Data0_n: %b, Data1_n: %b, Data2_n: %b",
|
|||
|
|
data_out0_n, data_out1_n, data_out2_n);
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
// 检查差分对一致性
|
|||
|
|
if ((data_out0_p === ~data_out0_n) &&
|
|||
|
|
(data_out1_p === ~data_out1_n) &&
|
|||
|
|
(data_out2_p === ~data_out2_n)) begin
|
|||
|
|
$display("[PASS] Test Case %0d: 差分对极性正确", test_case);
|
|||
|
|
end else begin
|
|||
|
|
$display("[FAIL] Test Case %0d: 差分对极性错误", test_case);
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
endtask
|
|||
|
|
|
|||
|
|
// 主要测试向量
|
|||
|
|
initial begin
|
|||
|
|
// 初始化信号
|
|||
|
|
clk_in_p = 1'b1;
|
|||
|
|
clk_in_n = 1'b0;
|
|||
|
|
data_in_p = 3'b000;
|
|||
|
|
data_in_n = 3'b111;
|
|||
|
|
|
|||
|
|
$display("=== LVDS信号复制模块仿真开始 ===");
|
|||
|
|
$display("时钟周期: %0t ns", CLK_PERIOD);
|
|||
|
|
$timeformat(-9, 0, " ns", 10);
|
|||
|
|
|
|||
|
|
// 等待复位完成
|
|||
|
|
#(CLK_PERIOD * 2);
|
|||
|
|
|
|||
|
|
// 测试用例1: 全0数据
|
|||
|
|
$display("\n--- 测试用例1: 输入全0 ---");
|
|||
|
|
generate_diff_data(3'b000);
|
|||
|
|
#(CLK_PERIOD * 3); // 等待多个周期稳定
|
|||
|
|
check_output_sync(1);
|
|||
|
|
|
|||
|
|
// 测试用例2: 全1数据
|
|||
|
|
$display("\n--- 测试用例2: 输入全1 ---");
|
|||
|
|
generate_diff_data(3'b111);
|
|||
|
|
#(CLK_PERIOD * 3);
|
|||
|
|
check_output_sync(2);
|
|||
|
|
|
|||
|
|
// 测试用例3: 递增模式
|
|||
|
|
$display("\n--- 测试用例3: 数据递增模式 ---");
|
|||
|
|
for (integer i = 0; i < 8; i = i + 1) begin
|
|||
|
|
generate_diff_data(i);
|
|||
|
|
#(CLK_PERIOD);
|
|||
|
|
$display("时间 %t: 输入数据 %b -> 输出0_p %b", $time, i, data_out0_p);
|
|||
|
|
if (i > 0) check_output_sync(3);
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
// 测试用例4: 随机数据
|
|||
|
|
$display("\n--- 测试用例4: 随机数据测试 ---");
|
|||
|
|
for (integer j = 0; j < 10; j = j + 1) begin
|
|||
|
|
generate_diff_data($random % 8);
|
|||
|
|
#(CLK_PERIOD);
|
|||
|
|
check_output_sync(4);
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
// 测试用例5: 快速数据变化
|
|||
|
|
$display("\n--- 测试用例5: 快速数据变化测试 ---");
|
|||
|
|
repeat(5) begin
|
|||
|
|
generate_diff_data(3'b010);
|
|||
|
|
#(CLK_PERIOD/4);
|
|||
|
|
generate_diff_data(3'b101);
|
|||
|
|
#(CLK_PERIOD/4);
|
|||
|
|
generate_diff_data(3'b110);
|
|||
|
|
#(CLK_PERIOD/4);
|
|||
|
|
generate_diff_data(3'b001);
|
|||
|
|
#(CLK_PERIOD/4);
|
|||
|
|
check_output_sync(5);
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
// 测试用例6: 验证寄存器延迟
|
|||
|
|
$display("\n--- 测试用例6: 寄存器延迟验证 ---");
|
|||
|
|
generate_diff_data(3'b010);
|
|||
|
|
#(CLK_PERIOD/2); // 半周期后检查
|
|||
|
|
if ((data_out0_p !== 3'b010) &&
|
|||
|
|
(data_out0_p === data_out1_p) &&
|
|||
|
|
(data_out1_p === data_out2_p)) begin
|
|||
|
|
$display("[PASS] 寄存器延迟正确:输出尚未更新");
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
#(CLK_PERIOD/2); // 完整周期后检查
|
|||
|
|
if ((data_out0_p === 3'b010) &&
|
|||
|
|
(data_out0_p === data_out1_p) &&
|
|||
|
|
(data_out1_p === data_out2_p)) begin
|
|||
|
|
$display("[PASS] 寄存器延迟正确:输出已更新");
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
$display("\n=== 仿真完成 ===");
|
|||
|
|
#100 $finish;
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
// 监控关键信号
|
|||
|
|
initial begin
|
|||
|
|
$monitor("时间 %t: 输入=%b, 输出0_p=%b, 输出1_p=%b, 输出2_p=%b",
|
|||
|
|
$time, data_in_p, data_out0_p, data_out1_p, data_out2_p);
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
// 波形文件生成(用于Vivado仿真)
|
|||
|
|
initial begin
|
|||
|
|
$dumpfile("lvds_1to3_copy_reg.vcd");
|
|||
|
|
$dumpvars(0, tb_lvds_1to3_copy_reg);
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
endmodule
|