把uart_ctrl_systemreg和 sys_regfile文件简单写完了,仿真没问题了
This commit is contained in:
parent
9be3e4a483
commit
be7c6d5c78
|
|
@ -21,6 +21,43 @@
|
|||
|
||||
|
||||
module digital_top(
|
||||
|
||||
input clk,
|
||||
input rst_n,
|
||||
input uart_rx,
|
||||
output uart_tx
|
||||
);
|
||||
|
||||
wire [31:0] w_wrdata; // DUT -> SRAM 写数据
|
||||
wire [24:0] w_addr; // DUT -> SRAM 地址
|
||||
wire w_wren; // 写使能
|
||||
wire w_rden; // 读使能
|
||||
wire [31:0] w_rddata; // SRAM -> DUT 读数据
|
||||
|
||||
|
||||
// 例化待测模块 (DUT)
|
||||
uart_ctrl_sysreg #(
|
||||
.BAUD (115200),
|
||||
.CLOCK_FREQ (50_000_000)
|
||||
) u_uart_ctrl (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.uart_rx (uart_rx),
|
||||
.uart_tx (uart_tx),
|
||||
.o_wrdata (w_wrdata),
|
||||
.o_addr (w_addr),
|
||||
.o_wren (w_wren),
|
||||
.o_rden (w_rden),
|
||||
.i_rddata (w_rddata)
|
||||
);
|
||||
|
||||
system_regfile u_system_regfile (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.wrdata (w_wrdata),
|
||||
.wren (w_wren),
|
||||
.rwaddr (w_addr),
|
||||
.rden (w_rden),
|
||||
.rddata (w_rddata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -45,8 +45,9 @@ module uart_ctrl_sysreg #(
|
|||
localparam S_IDLE = 3'd0,
|
||||
S_RX_CMD_L = 3'd1,
|
||||
S_PARSE = 3'd2,
|
||||
S_RD_DATA = 3'd3,
|
||||
S_WR_DATA = 3'd4;
|
||||
S_WAIT_RD = 3'd3,
|
||||
S_RD_DATA = 3'd4,
|
||||
S_WR_DATA = 3'd5;
|
||||
|
||||
|
||||
|
||||
|
|
@ -81,19 +82,22 @@ module uart_ctrl_sysreg #(
|
|||
data_bytes_len <= cmd_reg[19:0];
|
||||
if(cmd_reg[63] == 1'b1) begin //读指令
|
||||
o_rden <= 1'b1;
|
||||
state <= S_RD_DATA;
|
||||
state <= S_WAIT_RD;
|
||||
end
|
||||
else begin //写指令
|
||||
state <= S_WR_DATA;
|
||||
end
|
||||
end
|
||||
S_RD_DATA :begin //3
|
||||
S_WAIT_RD : begin //3
|
||||
o_rden <= 1'b0;
|
||||
state <= S_RD_DATA;
|
||||
end
|
||||
S_RD_DATA :begin //4
|
||||
uart_tx_data <= i_rddata;
|
||||
uart_tx_go <= 1'b1;
|
||||
state <= S_IDLE;
|
||||
end
|
||||
S_WR_DATA : begin //4
|
||||
S_WR_DATA : begin //5
|
||||
o_wren <= 1'b0;
|
||||
if(data_bytes_len != 0)begin
|
||||
if(uart_rx_done) begin
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
`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
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
`timescale 1ns / 1ps
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 2026/04/03 22:09:36
|
||||
// Design Name:
|
||||
// Module Name: tb_diginal_top
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool Versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
module tb_diginal_top();
|
||||
|
||||
reg clk;
|
||||
reg rst_n;
|
||||
wire uart_tx;
|
||||
reg uart_rx;
|
||||
|
||||
parameter CLK_PERIOD = 20; // 50MHz
|
||||
parameter BAUD = 115200; // 提高波特率加快仿真
|
||||
localparam BIT_TIME = 1_000_000_000 / BAUD; // 计算1比特持续的ns数
|
||||
|
||||
initial clk = 0;
|
||||
always #(CLK_PERIOD/2) clk = ~clk;
|
||||
|
||||
digital_top u_digital_top(
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.uart_rx(uart_rx),
|
||||
.uart_tx(uart_tx)
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// 模拟上位机:字节发送任务 (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[7:0]);
|
||||
send_byte(data[15:8]);
|
||||
send_byte(data[23:16]);
|
||||
send_byte(data[31:24]);
|
||||
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
|
||||
endmodule
|
||||
Loading…
Reference in New Issue