thermometer_digital/tb/TB_top.sv

155 lines
4.7 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_top();
// ==========================================
// 参数与信号定义
// ==========================================
parameter CLK_PERIOD = 20; // 50MHz
parameter BAUD = 115200;
localparam BIT_TIME = 1_000_000_000 / BAUD;
reg clk;
reg rst_n;
reg uart_rx; // 对应 DUT 的 RX
wire uart_tx; // 对应 DUT 的 TX
// 时钟生成
initial clk = 0;
always #(CLK_PERIOD/2) clk = ~clk;
// ==========================================
// 实例化被测设计 (DUT)
// ==========================================
digital_top u_digital_top(
.clk (clk),
.rst_n (rst_n),
.uart_rx (uart_rx),
.uart_tx (uart_tx)
);
// ==========================================
// 任务:发送一个字节 (Serial TX)
// ==========================================
task automatic send_byte(input [7:0] data);
begin
uart_rx = 0; // 起始位
#(BIT_TIME);
for (int i = 0; i < 8; i++) begin
uart_rx = data[i]; // LSB First
#(BIT_TIME);
end
uart_rx = 1; // 停止位
#(BIT_TIME);
end
endtask
// 任务:发送 32/64 位数据
task automatic send_data(input [63:0] data, input int len_bits);
int bytes = len_bits / 8;
for (int i = 0; i < bytes; i++) begin
// 默认小端发送:低字节在前
send_byte(data[i*8 +: 8]);
end
endtask
// ==========================================
// 流程控制TX 驱动 (从 case.txt 读取)
// ==========================================
initial begin
int file_h;
int status;
logic [63:0] val;
// 初始化信号
rst_n = 0;
uart_rx = 1;
#(CLK_PERIOD * 10);
rst_n = 1;
file_h = $fopen("case.txt", "r");
if (!file_h) begin
$display("[TX ERROR] Cannot open case.txt");
$finish;
end
$display("[TX] Starting transmission...");
while (!$feof(file_h)) begin
// 假设文件中每行是一个 hex 数据
status = $fscanf(file_h, "%h\n", val);
if (status == 1) begin
if (val > 64'hFFFF_FFFF) begin
$display("[%t] TX CMD: %h", $time, val);
send_data(val, 64);
end else begin
$display("[%t] TX DATA: %h", $time, val[31:0]);
send_data(val[31:0], 32);
end
#(BIT_TIME * 5); // 帧间隙
end
end
$fclose(file_h);
$display("[TX] All cases sent.");
// 等待一段时间观察 RX 是否还有回传,然后结束
#(BIT_TIME * 500);
$display("[SIM] Simulation finished.");
$finish;
end
// ==========================================
// 流程控制RX 监听 (保存到 rx_data.txt)
// ==========================================
int rx_file_h;
initial begin
logic [7:0] rx_byte;
rx_file_h = $fopen("rx_data.txt", "w");
if (!rx_file_h) begin
$display("[RX ERROR] Cannot create rx_data.txt");
$finish;
end
forever begin
logic [31:0] packet_word; // 32位数据包
logic [7:0] rx_byte;
// 收集4个字节并组合成32位数据
for (int byte_idx = 0; byte_idx < 4; byte_idx++) begin
// 1. 等待起始位 (下降沿)
@(negedge uart_tx);
// 2. 跳过起始位,采样数据中心点
#(BIT_TIME / 2);
#(BIT_TIME);
// 读取8个数据位
for (int i = 0; i < 8; i++) begin
rx_byte[i] = uart_tx;
#(BIT_TIME);
end
// 组合成32位数据小端序先收到的在低位
packet_word[8*byte_idx +: 8] = rx_byte;
$display("[%t] Byte %0d: 0x%h", $time, byte_idx, rx_byte);
// 等待停止位结束
if (byte_idx < 3) begin
#(BIT_TIME / 2);
end
end
// 写入文件一行一个32位数据
$fdisplay(rx_file_h, "%08h", packet_word);
$display("[%t] Packet (32-bit): 0x%08h", $time, packet_word);
// 等待最后一个字节的停止位结束
#(BIT_TIME / 2);
end
end
final begin
if (rx_file_h) begin
$fclose(rx_file_h);
$display("[RX] File closed at %t",$time);
end
end
endmodule