154 lines
4.6 KiB
Verilog
154 lines
4.6 KiB
Verilog
`timescale 1ns / 1ps
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
// Company:
|
|
// Engineer:
|
|
//
|
|
// Create Date: 2026/03/31 13:01:26
|
|
// Design Name:
|
|
// Module Name: tb_uart_ctrl_sysreg
|
|
// Project Name:
|
|
// Target Devices:
|
|
// Tool Versions:
|
|
// Description:
|
|
//
|
|
// Dependencies:
|
|
//
|
|
// Revision:
|
|
// Revision 0.01 - File Created
|
|
// Additional Comments:
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
`timescale 1ns / 1ps
|
|
|
|
module tb_uart_ctrl_sysreg();
|
|
|
|
// --- 参数与信号 ---
|
|
parameter CLK_PERIOD = 20; // 50MHz
|
|
parameter BAUD = 115200; // 提高波特率加快仿真
|
|
localparam BIT_TIME = 1_000_000_000 / BAUD; // 计算1比特持续的ns数
|
|
|
|
// 端口信号
|
|
reg clk;
|
|
reg rst_n;
|
|
reg uart_rx; // 发给 DUT 的 UART 数据
|
|
wire uart_tx; // DUT 回发数据
|
|
wire [31:0] o_wrdata; // DUT -> SRAM 写数据
|
|
wire [24:0] o_addr; // DUT -> SRAM 地址
|
|
wire o_wren; // 写使能
|
|
wire o_rden; // 读使能
|
|
reg [31:0] i_rddata; // SRAM -> DUT 读数据
|
|
|
|
// 例化待测模块 (DUT)
|
|
uart_ctrl_sysreg #(
|
|
.BAUD (BAUD),
|
|
.CLOCK_FREQ (50_000_000)
|
|
) u_dut (
|
|
.clk (clk),
|
|
.rst_n (rst_n),
|
|
.uart_rx (uart_rx),
|
|
.uart_tx (uart_tx),
|
|
.o_wrdata (o_wrdata),
|
|
.o_addr (o_addr),
|
|
.o_wren (o_wren),
|
|
.o_rden (o_rden),
|
|
.i_rddata (i_rddata)
|
|
);
|
|
// --- 时钟产生 ---
|
|
initial clk = 0;
|
|
always #(CLK_PERIOD/2) clk = ~clk;
|
|
|
|
// ============================================================
|
|
// 模拟上位机:字节发送任务 (Serial UART TX)
|
|
// ============================================================
|
|
task send_byte;
|
|
input [7:0] data;
|
|
integer i;
|
|
begin
|
|
uart_rx = 0; // 起始位
|
|
#(BIT_TIME);
|
|
for (i = 0; i < 8; i = i + 1) begin
|
|
uart_rx = data[i]; // 数据位 (LSB first)
|
|
#(BIT_TIME);
|
|
end
|
|
uart_rx = 1; // 停止位
|
|
#(BIT_TIME);
|
|
#(BIT_TIME); // 字节间隙
|
|
end
|
|
endtask
|
|
|
|
// 发送 32 位数据 (拆分为 4 个字节)
|
|
task send_32bit;
|
|
input [31:0] data;
|
|
begin
|
|
// 注意:这里发送顺序要和你的串口接收模块端序一致
|
|
// 假设大端发送:先发 [7:0]
|
|
send_byte(data[31:24]);
|
|
send_byte(data[23:16]);
|
|
send_byte(data[15:8]);
|
|
send_byte(data[7:0]);
|
|
end
|
|
endtask
|
|
|
|
// ============================================================
|
|
// 主测试流程
|
|
// ============================================================
|
|
integer file_ptr;
|
|
integer status;
|
|
reg [63:0] temp_cmd;
|
|
reg [31:0] temp_data;
|
|
|
|
initial begin
|
|
// 初始化
|
|
rst_n = 0;
|
|
uart_rx = 1;
|
|
#(CLK_PERIOD * 10);
|
|
rst_n = 1;
|
|
#(CLK_PERIOD * 100);
|
|
|
|
// 打开测试文件
|
|
file_ptr = $fopen("D:/shortname/thermometer/try/test_cases.txt", "r");
|
|
if (file_ptr == 0) begin
|
|
$display("====Error: can not open test_cases.txt file!===");
|
|
$finish;
|
|
end
|
|
|
|
$display("======= Begin Send Case =======");
|
|
|
|
while (!$feof(file_ptr)) begin
|
|
// 尝试读取一行(先尝试按 64 位 CMD 读取)
|
|
status = $fscanf(file_ptr, "%h\n", temp_cmd);
|
|
|
|
if (status == 1) begin
|
|
if (temp_cmd > 64'hFFFF_FFFF) begin
|
|
// 如果读到的是 64 位,认为是 CMD
|
|
$display("[%t] Send command frame: 0x%h", $time, temp_cmd);
|
|
send_32bit(temp_cmd[63:32]); // 先发高32位
|
|
send_32bit(temp_cmd[31:0]); // 再发低32位
|
|
end else begin
|
|
// 如果读到的是 32 位,认为是 DATA
|
|
$display("[%t] Send data stream: 0x%h", $time, temp_cmd[31:0]);
|
|
send_32bit(temp_cmd[31:0]);
|
|
end
|
|
end
|
|
#(BIT_TIME * 20); // 指令/数据组之间的间隔
|
|
end
|
|
|
|
$display("======= All Cases Sent =======");
|
|
$fclose(file_ptr);
|
|
|
|
#(BIT_TIME * 200);
|
|
$stop;
|
|
end
|
|
|
|
// ============================================================
|
|
// 监听回传:捕捉 FPGA 返回的读数据
|
|
// ============================================================
|
|
// 简单起见,这里直接观察波形,或者你可以写一个串口接收任务
|
|
initial begin
|
|
$display("[%t] 监听器已启动...", $time);
|
|
end
|
|
|
|
endmodule
|