初始的工程参考

This commit is contained in:
2026-02-02 17:58:25 +08:00
parent 2573559951
commit 2bd575c8ea
5 changed files with 850 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2026/01/25 21:01:38
// Design Name:
// Module Name: lvds_1to3_copy_reg
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module lvds_1to3_copy_reg (
// 输入LVDS差分信号
input wire clk_in_p, clk_in_n,
input wire [2:0] data_in_p, data_in_n,
// 输出LVDS差分信号
output wire clk_out0_p, clk_out0_n,
output wire clk_out1_p, clk_out1_n,
output wire clk_out2_p, clk_out2_n,
output wire [2:0] data_out0_p, data_out0_n,
output wire [2:0] data_out1_p, data_out1_n,
output wire [2:0] data_out2_p, data_out2_n
);
// 输入缓冲
wire clk_ibuf;
wire [2:0] data_ibuf;
IBUFDS clk_ibuf_inst (.O(clk_ibuf), .I(clk_in_p), .IB(clk_in_n));
generate
for (genvar i = 0; i < 3; i = i + 1) begin
IBUFDS data_ibuf_inst (.O(data_ibuf[i]), .I(data_in_p[i]), .IB(data_in_n[i]));
end
endgenerate
// 全局时钟
wire clk_bufg;
BUFG bufg_inst (.I(clk_ibuf), .O(clk_bufg));
// 寄存器同步
reg [2:0] data_sync0, data_sync1, data_sync2;
always @(posedge clk_bufg) begin
data_sync0 <= data_ibuf;
data_sync1 <= data_ibuf;
data_sync2 <= data_ibuf;
end
// 输出缓冲
generate
for (genvar i = 0; i < 3; i = i + 1) begin
OBUFDS data_obuf0_inst (.O(data_out0_p[i]), .OB(data_out0_n[i]), .I(data_sync0[i]));
OBUFDS data_obuf1_inst (.O(data_out1_p[i]), .OB(data_out1_n[i]), .I(data_sync1[i]));
OBUFDS data_obuf2_inst (.O(data_out2_p[i]), .OB(data_out2_n[i]), .I(data_sync2[i]));
end
endgenerate
// 时钟输出缓冲
OBUFDS clk_obuf0_inst (.O(clk_out0_p), .OB(clk_out0_n), .I(clk_bufg));
OBUFDS clk_obuf1_inst (.O(clk_out1_p), .OB(clk_out1_n), .I(clk_bufg));
OBUFDS clk_obuf2_inst (.O(clk_out2_p), .OB(clk_out2_n), .I(clk_bufg));
endmodule

View File

@@ -0,0 +1,178 @@
`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