thermometer_digital/uart_thermometer_digital/tb/tb_uart_top_32bit.v

113 lines
3.0 KiB
Verilog

`timescale 1ns / 1ps
module tb_uart_top_32bit();
// --- 参数定义 ---
parameter CLK_PERIOD = 20;
parameter BAUD = 115200; // 提高波特率可以加快仿真速度
parameter CLOCK_FREQ = 50_000_000;
// --- 信号声明 ---
reg Clk;
reg Reset_n;
reg Send_Go32;
reg [31:0] Tx_Data32;
wire uart_tx;
wire uart_rx;
wire Tx_Done32;
wire Rx_Done32;
wire [31:0] Rx_Data32;
// --- 实例化 DUT ---
uart_top_32bit #(
.BAUD(BAUD),
.CLOCK_FREQ(CLOCK_FREQ)
) dut (
.Clk(Clk),
.Reset_n(Reset_n),
.Send_Go32(Send_Go32),
.Tx_Data32(Tx_Data32),
.Tx_Done32(Tx_Done32),
.uart_tx(uart_tx),
.uart_rx(uart_rx),
.Rx_Done32(Rx_Done32),
.Rx_Data32(Rx_Data32)
);
// 构造回环
assign uart_rx = uart_tx;
// 时钟产生
initial Clk = 0;
always #(CLK_PERIOD/2) Clk = ~Clk;
// ============================================================
// 发送并校验的任务 (Task)
// ============================================================
task send_and_check;
input [31:0] data;
begin
Tx_Data32 = data;
Send_Go32 = 1;
#(CLK_PERIOD);
Send_Go32 = 0;
// 等待发送和接收全部完成
fork
wait(Rx_Done32);
wait(Tx_Done32);
join
#(CLK_PERIOD * 10); // 留一点余量
if (Rx_Data32 === data)
$display("[PASS] 发送: 0x%h | 接收: 0x%h", data, Rx_Data32);
else
$display("[FAIL] 发送: 0x%h | 接收: 0x%h !!! 错误 !!!", data, Rx_Data32);
#(CLK_PERIOD * 100); // 两次发送间的间隔
end
endtask
// ============================================================
// 测试流程
// ============================================================
integer i;
initial begin
// 初始化
Reset_n = 0;
Send_Go32 = 0;
Tx_Data32 = 0;
// 复位
#(CLK_PERIOD * 10);
Reset_n = 1;
#(CLK_PERIOD * 10);
$display("======= 开始 32位串口回环测试 =======");
// 1. 基础边界测试
send_and_check(32'h0000_0000);
send_and_check(32'hFFFF_FFFF);
// 2. 经典交替位测试 (检查串扰和采样)
send_and_check(32'hAAAA_AAAA);
send_and_check(32'h5555_5555);
// 3. 随机/特殊数据测试
send_and_check(32'h1234_5678);
send_and_check(32'h8765_4321);
send_and_check(32'hDEAD_BEEF);
// 4. 循环自动测试 (测试 5 组递增数据)
for (i = 0; i < 5; i = i + 1) begin
send_and_check(32'h2024_0000 + i);
end
$display("======= 所有测试用例执行完毕 =======");
#(CLK_PERIOD * 200);
$stop;
end
endmodule