Compare commits
3 Commits
be7c6d5c78
...
c38356bc50
| Author | SHA1 | Date |
|---|---|---|
|
|
c38356bc50 | |
|
|
81852b1579 | |
|
|
9e3862f694 |
|
|
@ -2,77 +2,87 @@
|
|||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Engineer: Yangshenbo
|
||||
// version:V1.0
|
||||
// Create Date: 2026/03/22
|
||||
// Create Date: 2026/04/05
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
module digital_thermometer(
|
||||
input clk,
|
||||
input rst_n,
|
||||
input vin,
|
||||
input mode,
|
||||
output reg [19:0]freq_x100hz,
|
||||
output reg [15:0]temp_out,
|
||||
output reg temp_valid
|
||||
input sig_in,
|
||||
input [23:0]win_us,
|
||||
input [1:0]out_mode, //0输出对应温度, 1输出对应的频率,2单位窗口输出脉冲的个数
|
||||
input [15:0]temp_85_fre_k, //85°对应的频率,默认为600khz
|
||||
input [15:0]temp_neg_40_fre_k , //-40对应的频率,默认为160khz,单位khz
|
||||
input report_en, //主动上报使能
|
||||
input [23:0]rep_gap_us, //最小位win_us
|
||||
output reg [23:0]therm_out,
|
||||
output reg therm_vld
|
||||
);
|
||||
|
||||
wire [19:0] freq;
|
||||
wire freq_valid;
|
||||
|
||||
|
||||
//映射表:
|
||||
reg [15:0] temp_lut [0:800];
|
||||
integer i;
|
||||
initial begin
|
||||
for (i = 0; i <= 800; i = i + 1) begin
|
||||
// 50.0kHz->-40°C, 130.0kHz->85°C
|
||||
// temp = -400 + (1250 * i) / 800
|
||||
temp_lut[i] = -400 + (1250 * i + 400) / 800;
|
||||
wire [23:0] wd_cnt_out;
|
||||
wire wd_cnt_vld;
|
||||
reg [23:0] gap_cnt; // 上报间隔计数器
|
||||
wire [23:0] cur_freq_khz;
|
||||
reg signed [31:0] temp_scaled;
|
||||
|
||||
assign cur_freq_khz = (wd_cnt_out * 1000) / win_us;
|
||||
//我们将温度结果放大100倍
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
temp_scaled <= 0;
|
||||
end else if (wd_cnt_vld) begin
|
||||
// 线性插值计算
|
||||
temp_scaled <= ((cur_freq_khz - temp_neg_40_fre_k) * 12500) / (temp_85_fre_k - temp_neg_40_fre_k) - 4000;
|
||||
end
|
||||
end
|
||||
|
||||
// 上报逻辑与输出选择
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
gap_cnt <= 0;
|
||||
therm_vld <= 0;
|
||||
therm_out <= 0;
|
||||
end else if (wd_cnt_vld) begin
|
||||
if (report_en) begin
|
||||
if (gap_cnt >= (rep_gap_us / win_us) - 1) begin
|
||||
gap_cnt <= 0;
|
||||
therm_vld <= 1'b1;
|
||||
end else begin
|
||||
gap_cnt <= gap_cnt + 1'b1;
|
||||
therm_vld <= 1'b0;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
gap_cnt <= 0;
|
||||
therm_vld <= 1'b0;
|
||||
end
|
||||
|
||||
// 模式切换输出
|
||||
case (out_mode)
|
||||
2'd0: therm_out <= temp_scaled[23:0]; // 输出放大100倍的温度
|
||||
2'd1: therm_out <= cur_freq_khz; // 输出频率(kHz)
|
||||
2'd2: therm_out <= wd_cnt_out; // 输出原始脉冲计数值
|
||||
default: therm_out <= temp_scaled[23:0];
|
||||
endcase
|
||||
end
|
||||
else begin
|
||||
therm_vld <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
freq_x100hz <= 0;
|
||||
temp_out <= 0;
|
||||
temp_valid <= 0;
|
||||
end
|
||||
else begin
|
||||
temp_valid <= freq_valid;
|
||||
|
||||
if (freq_valid) begin
|
||||
freq_x100hz <= freq;
|
||||
|
||||
if (mode == 0) begin
|
||||
// 模式0:线性输出
|
||||
// 频率范围:500~1300(50.0kHz~130.0kHz)
|
||||
if (freq < 500)
|
||||
temp_out <= -400;
|
||||
else if (freq > 1300)
|
||||
temp_out <= 850;
|
||||
else
|
||||
temp_out <= -400 + ((freq - 500) * 1250) / 800;
|
||||
end else begin
|
||||
// 模式1:查表输出
|
||||
if (freq < 500)
|
||||
temp_out <= temp_lut[0];
|
||||
else if (freq > 1300)
|
||||
temp_out <= temp_lut[800];
|
||||
else
|
||||
temp_out <= temp_lut[freq - 500];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
pulse_freq_10ms u_freq_measure (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.vin (vin),
|
||||
.freq (freq), //1302 ->130.2KHz
|
||||
.valid (freq_valid)
|
||||
// 实例化被测模块
|
||||
pulse_cnt #(
|
||||
.CLK_FREQ(50_000_000)
|
||||
) pulse_cnt_inst (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.sig_in (sig_in),
|
||||
.win_us (win_us),
|
||||
.cnt_out(wd_cnt_out),
|
||||
.vld_out(wd_cnt_vld)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
`timescale 1ns / 1ps
|
||||
|
||||
module pulse_cnt #(
|
||||
parameter CLK_FREQ = 50_000_000
|
||||
) (
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
input wire sig_in,
|
||||
input wire [23:0] win_us,
|
||||
output reg [23:0] cnt_out,
|
||||
output reg vld_out
|
||||
);
|
||||
|
||||
|
||||
reg [31:0] window_cnt; // 当前时钟周期计数
|
||||
reg [31:0] target_cnt; // 当前窗口所需时钟周期数
|
||||
|
||||
// 脉冲计数(宽度与输出一致,防止溢出)
|
||||
reg [23:0] pulse_cnt;
|
||||
|
||||
// 标志:是否正在计算新的 target_cnt(避免组合逻辑环路)
|
||||
reg calc_done;
|
||||
|
||||
reg sig_sync1, sig_sync2, sig_sync3;
|
||||
wire sig_rise = sig_sync2 & ~sig_sync3;
|
||||
|
||||
always @(posedge clk) begin
|
||||
sig_sync1 <= sig_in;
|
||||
sig_sync2 <= sig_sync1;
|
||||
sig_sync3 <= sig_sync2;
|
||||
end
|
||||
|
||||
// 主控制逻辑
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
window_cnt <= 0;
|
||||
pulse_cnt <= 0;
|
||||
cnt_out <= 0;
|
||||
vld_out <= 0;
|
||||
target_cnt <= 24'd50_000;
|
||||
|
||||
end else begin
|
||||
vld_out <= 1'b0;
|
||||
target_cnt <= ( {40'd0, win_us} * CLK_FREQ) / 1_000_000 ;
|
||||
// 窗口计数结束条件:当前计数值到达 target_cnt
|
||||
if (window_cnt >= target_cnt) begin
|
||||
cnt_out <= pulse_cnt;
|
||||
vld_out <= 1'b1;
|
||||
// 复位窗口计数器与脉冲计数器,并触发重新计算目标值
|
||||
window_cnt <= 0;
|
||||
pulse_cnt <= 0;
|
||||
end else begin
|
||||
window_cnt <= window_cnt + 1;
|
||||
if (sig_rise)
|
||||
pulse_cnt <= pulse_cnt + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
`timescale 1ns / 1ps
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Company:
|
||||
// Engineer:
|
||||
//
|
||||
// Create Date: 2026/03/22 18:53:43
|
||||
// Design Name:
|
||||
// Module Name: pulse_freq_10ms
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool Versions:
|
||||
// Description:
|
||||
//
|
||||
// Dependencies:
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module pulse_freq_10ms #(
|
||||
parameter CLK_FREQ = 50_000_000, // 系统时钟频率(Hz),默认50MHz
|
||||
parameter WINDOW_MS = 10 // 测量时间窗口(ms),默认10ms
|
||||
) (
|
||||
input clk, // 系统时钟
|
||||
input rst_n, // 异步复位,低有效
|
||||
input vin, // 输入方波
|
||||
output reg [19:0] freq, // 时间窗口内脉冲计数(如果为1302,就是130.2k)
|
||||
output reg valid // 测量完成有效脉冲
|
||||
);
|
||||
|
||||
// 计算窗口计数最大值
|
||||
localparam WINDOW_CNT = (CLK_FREQ / 1000) * WINDOW_MS - 1;
|
||||
|
||||
reg [31:0] cnt_window; // 窗口计时器(使用32位以防大数值)
|
||||
reg [19:0] pulse_cnt; // 脉冲计数器
|
||||
reg vin_sync1, vin_sync2;
|
||||
wire vin_rise;
|
||||
|
||||
// 边沿检测
|
||||
always @(posedge clk) begin
|
||||
vin_sync1 <= vin;
|
||||
vin_sync2 <= vin_sync1;
|
||||
end
|
||||
assign vin_rise = vin_sync1 & ~vin_sync2;
|
||||
|
||||
// 核心逻辑:窗口计数 + 脉冲计数 + 锁存输出
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
cnt_window <= 0;
|
||||
pulse_cnt <= 0;
|
||||
valid <= 0;
|
||||
end else begin
|
||||
valid <= 0; // 默认无效
|
||||
if (cnt_window == WINDOW_CNT) begin // 窗口时间到
|
||||
freq <= pulse_cnt; // 输出计数值
|
||||
valid <= 1;
|
||||
cnt_window <= 0;
|
||||
pulse_cnt <= 0;
|
||||
end else begin
|
||||
cnt_window <= cnt_window + 1;
|
||||
if (vin_rise) pulse_cnt <= pulse_cnt + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -62,7 +62,7 @@ module uart_top_32bit #(
|
|||
end
|
||||
|
||||
1, 2, 3, 4: begin // 依次发送字节0, 1, 2, 3
|
||||
byte_tx_data_reg <= tx_data_buffer[7:0]; // 优先发低位(小端)
|
||||
byte_tx_data_reg <= tx_data_buffer[31:24]; // 优先发高位置(大端)
|
||||
byte_tx_go_reg <= 1;
|
||||
tx_state <= tx_state + 4; // 跳转到等待状态 (利用加法偏移)
|
||||
end
|
||||
|
|
@ -71,7 +71,7 @@ module uart_top_32bit #(
|
|||
5, 6, 7, 8: begin
|
||||
byte_tx_go_reg <= 0;
|
||||
if (byte_tx_done) begin
|
||||
tx_data_buffer <= tx_data_buffer >> 8; // 移位,准备下一字节
|
||||
tx_data_buffer <= tx_data_buffer << 8; // 移位,准备下一字节
|
||||
if (tx_state == 8) tx_state <= 0; // 发完4个
|
||||
else tx_state <= tx_state - 3; // 回到下一个发送状态
|
||||
end
|
||||
|
|
@ -97,12 +97,12 @@ module uart_top_32bit #(
|
|||
end else begin
|
||||
rx_done32_reg <= 0;
|
||||
if (byte_rx_done) begin
|
||||
// 拼接数据 (小端模式)
|
||||
// 拼接数据 (大端模式)
|
||||
case(rx_cnt)
|
||||
0: rx_data_buffer[7:0] <= byte_rx_data;
|
||||
1: rx_data_buffer[15:8] <= byte_rx_data;
|
||||
2: rx_data_buffer[23:16] <= byte_rx_data;
|
||||
3: rx_data_buffer[31:24] <= byte_rx_data;
|
||||
0: rx_data_buffer[31:24] <= byte_rx_data;
|
||||
1: rx_data_buffer[23:16] <= byte_rx_data;
|
||||
2: rx_data_buffer[15:8] <= byte_rx_data;
|
||||
3: rx_data_buffer[7:0] <= byte_rx_data;
|
||||
endcase
|
||||
|
||||
if (rx_cnt == 3) begin
|
||||
|
|
|
|||
|
|
@ -47,8 +47,7 @@ module TB_top();
|
|||
// 任务:发送 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
|
||||
// 默认小端发送:低字节在前
|
||||
for (int i = bytes - 1; i >= 0; i--) begin // 从最高字节往下发
|
||||
send_byte(data[i*8 +: 8]);
|
||||
end
|
||||
endtask
|
||||
|
|
@ -128,7 +127,7 @@ module TB_top();
|
|||
#(BIT_TIME);
|
||||
end
|
||||
// 组合成32位数据(小端序:先收到的在低位)
|
||||
packet_word[8*byte_idx +: 8] = rx_byte;
|
||||
packet_word[24 - 8*byte_idx +: 8] = rx_byte;
|
||||
$display("[%t] Byte %0d: 0x%h", $time, byte_idx, rx_byte);
|
||||
// 等待停止位结束
|
||||
if (byte_idx < 3) begin
|
||||
|
|
@ -139,7 +138,6 @@ module TB_top();
|
|||
// 写入文件(一行一个32位数据)
|
||||
$fdisplay(rx_file_h, "%08h", packet_word);
|
||||
$display("[%t] Packet (32-bit): 0x%08h", $time, packet_word);
|
||||
|
||||
// 等待最后一个字节的停止位结束
|
||||
#(BIT_TIME / 2);
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,173 @@
|
|||
`timescale 1ns / 1ps
|
||||
|
||||
module tb_digital_thermometer();
|
||||
|
||||
// --- Parameter ---
|
||||
localparam CLK_PERIOD = 20; // 50MHz Clock
|
||||
|
||||
// --- Signals ---
|
||||
reg clk;
|
||||
reg rst_n;
|
||||
reg sig_in;
|
||||
reg [23:0] win_us;
|
||||
reg [1:0] out_mode;
|
||||
reg [15:0] temp_85_fre_k;
|
||||
reg [15:0] temp_neg_40_fre_k;
|
||||
reg report_en;
|
||||
reg [23:0] rep_gap_us;
|
||||
|
||||
wire [23:0] therm_out;
|
||||
wire therm_vld;
|
||||
|
||||
// --- DUT Instantiation ---
|
||||
digital_thermometer dut (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.sig_in (sig_in),
|
||||
.win_us (win_us),
|
||||
.out_mode (out_mode),
|
||||
.temp_85_fre_k (temp_85_fre_k),
|
||||
.temp_neg_40_fre_k (temp_neg_40_fre_k),
|
||||
.report_en (report_en),
|
||||
.rep_gap_us (rep_gap_us),
|
||||
.therm_out (therm_out),
|
||||
.therm_vld (therm_vld)
|
||||
);
|
||||
|
||||
// --- Clock Generation ---
|
||||
initial begin
|
||||
clk = 0;
|
||||
forever #(CLK_PERIOD/2) clk = ~clk;
|
||||
end
|
||||
|
||||
// --- Pulse Generation Task ---
|
||||
// freq_khz: Target frequency (kHz)
|
||||
// duration_ms: Test duration (ms)
|
||||
task automatic gen_pulses(input int freq_khz, input int duration_ms);
|
||||
int half_period_ns;
|
||||
longint end_time_ns;
|
||||
begin
|
||||
if (freq_khz <= 0) begin
|
||||
sig_in = 0;
|
||||
#(duration_ms * 1000000);
|
||||
end else begin
|
||||
half_period_ns = 500000 / freq_khz;
|
||||
end_time_ns = $time + (longint'(duration_ms) * 1000000);
|
||||
|
||||
$display("[%0t] Start generating signal: %0d kHz", $time, freq_khz);
|
||||
while ($time < end_time_ns) begin
|
||||
sig_in = 1;
|
||||
#(half_period_ns);
|
||||
sig_in = 0;
|
||||
#(half_period_ns);
|
||||
end
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
// // --- Basic Test Stimulus ---
|
||||
// initial begin
|
||||
// // 1. Initialize signals
|
||||
// rst_n = 0;
|
||||
// sig_in = 0;
|
||||
// win_us = 1000; // 1ms measurement window
|
||||
// out_mode = 0; // Default: temperature output
|
||||
// temp_85_fre_k = 600; // 85°C -> 600kHz
|
||||
// temp_neg_40_fre_k = 160; // -40°C -> 160kHz
|
||||
// report_en = 0;
|
||||
// rep_gap_us = 2000; // Report interval: 2ms
|
||||
|
||||
// // 2. Release reset
|
||||
// #(CLK_PERIOD * 10);
|
||||
// rst_n = 1;
|
||||
// #(CLK_PERIOD * 10);
|
||||
|
||||
// // --- Case 1: Test -40°C (160kHz) ---
|
||||
// $display("\n--- Test Case 1: -40°C (160kHz) time:%t---",$time);
|
||||
// gen_pulses(160, 5);
|
||||
|
||||
// // --- Case 2: Test 85°C (600kHz) ---
|
||||
// $display("\n--- Test Case 2: 85°C (600kHz) ---");
|
||||
// gen_pulses(600, 5);
|
||||
|
||||
// // --- Case 3: Test mid-range temperature (380kHz) ---
|
||||
// $display("\n--- Test Case 3: Mid-range (380kHz) ---");
|
||||
// gen_pulses(380, 5);
|
||||
|
||||
// // --- Case 4: Test output modes ---
|
||||
// $display("\n--- Test Case 4: Switch output modes ---");
|
||||
// out_mode = 1; // Frequency mode
|
||||
// gen_pulses(500, 3);
|
||||
// out_mode = 2; // Edge count mode
|
||||
// gen_pulses(500, 3);
|
||||
|
||||
// // --- Case 5: Test auto-report function ---
|
||||
// $display("\n--- Test Case 5: Auto-report enabled (2ms interval) ---");
|
||||
// out_mode = 0;
|
||||
// report_en = 1;
|
||||
// gen_pulses(300, 10);
|
||||
|
||||
// // End simulation
|
||||
// $display("\nSimulation finished at: %0t", $time);
|
||||
// #(CLK_PERIOD * 100);
|
||||
// $stop;
|
||||
// end
|
||||
|
||||
// --- Main Test: Verify Configuration & Report Interval ---
|
||||
initial begin
|
||||
// 1. Init
|
||||
rst_n = 0;
|
||||
sig_in = 0;
|
||||
win_us = 1000; // 1ms window
|
||||
out_mode = 0; // Mode 0: Temperature (x100 scale)
|
||||
report_en = 0;
|
||||
temp_neg_40_fre_k = 200;
|
||||
temp_85_fre_k = 700;
|
||||
rep_gap_us = 2000; // 2ms report gap
|
||||
|
||||
// 2. Release reset
|
||||
#(CLK_PERIOD * 10);
|
||||
rst_n = 1;
|
||||
#(CLK_PERIOD * 20);
|
||||
|
||||
// --- TEST 1: Verify frequency mapping configuration ---
|
||||
$display("\n[TEST 1] Verify frequency mapping parameters...");
|
||||
|
||||
$display(">> Input: 450kHz | Config: -40°C=200k, 85°C=700k | Expected temp: 2250");
|
||||
gen_pulses(450, 4);
|
||||
|
||||
temp_85_fre_k = 450;
|
||||
$display(">> Updated config: 85°C=450k | Input: 450kHz | Expected temp: 8500");
|
||||
gen_pulses(450, 4);
|
||||
|
||||
|
||||
// --- TEST 2: Verify rep_gap_us control ---
|
||||
$display("\n[TEST 2] Verify report interval (rep_gap_us)...");
|
||||
report_en = 1;
|
||||
|
||||
rep_gap_us = 2000;
|
||||
$display(">> rep_gap_us = 2ms (Expected vld every 2ms)");
|
||||
gen_pulses(300, 10);
|
||||
|
||||
rep_gap_us = 5000;
|
||||
$display(">> rep_gap_us = 5ms (Expected vld every 5ms)");
|
||||
gen_pulses(300, 15);
|
||||
|
||||
|
||||
// --- TEST 3: Boundary test (rep_gap_us < win_us) ---
|
||||
$display("\n[TEST 3] Boundary test: rep_gap_us < win_us");
|
||||
rep_gap_us = 500;
|
||||
gen_pulses(300, 5);
|
||||
|
||||
// End
|
||||
$display("\nConfiguration test completed at: %0t", $time);
|
||||
#(CLK_PERIOD * 100);
|
||||
$stop;
|
||||
end
|
||||
// --- Monitor ---
|
||||
initial begin
|
||||
$monitor("[%0t] Valid=%b | Mode=%0d | Result=%0d",
|
||||
$time, therm_vld, out_mode, therm_out);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
`timescale 1ns / 1ps
|
||||
|
||||
module tb_pulse_cnt();
|
||||
|
||||
// 参数定义
|
||||
localparam CLK_FREQ = 50_000_000; // 50 MHz 时钟
|
||||
localparam CLK_PERIOD = 20ns; // 1/50MHz = 20ns
|
||||
|
||||
// 信号声明
|
||||
reg clk;
|
||||
reg rst_n;
|
||||
reg [23:0] win_us;
|
||||
reg sig_in;
|
||||
wire [23:0] cnt_out;
|
||||
wire vld_out;
|
||||
|
||||
// 实例化被测模块
|
||||
pulse_cnt #(
|
||||
.CLK_FREQ(CLK_FREQ)
|
||||
) dut (
|
||||
.clk (clk),
|
||||
.rst_n (rst_n),
|
||||
.sig_in (sig_in),
|
||||
.win_us (win_us),
|
||||
.cnt_out(cnt_out),
|
||||
.vld_out(vld_out)
|
||||
);
|
||||
|
||||
// 时钟生成
|
||||
initial begin
|
||||
clk = 0;
|
||||
forever #(CLK_PERIOD/2) clk = ~clk;
|
||||
end
|
||||
|
||||
// 测试激励
|
||||
initial begin
|
||||
// 初始化
|
||||
rst_n = 0;
|
||||
win_us = 24'd1000; // 默认窗口 1000 us = 1 ms
|
||||
sig_in = 0;
|
||||
|
||||
// 释放复位
|
||||
repeat(5) @(posedge clk);
|
||||
rst_n = 1;
|
||||
repeat(2) @(posedge clk);
|
||||
|
||||
// --------------------------------------------------
|
||||
// 测试1:窗口内无脉冲
|
||||
// --------------------------------------------------
|
||||
$display("Test 1: No pulse, expect cnt_out = 0 after window");
|
||||
win_us = 24'd1000; // 1 ms 窗口
|
||||
wait (vld_out);
|
||||
$display(" cnt_out = %0d (expected 0)", cnt_out);
|
||||
#(CLK_PERIOD*2);
|
||||
|
||||
// --------------------------------------------------
|
||||
// 测试2:固定频率脉冲 50 kHz (周期 20 us)
|
||||
// --------------------------------------------------
|
||||
$display("Test 2: 50 kHz pulse, window = 1 ms -> expected 50 pulses");
|
||||
fork
|
||||
begin : pulse_gen
|
||||
forever begin
|
||||
#10us sig_in = 1;
|
||||
#10us sig_in = 0;
|
||||
end
|
||||
end
|
||||
join_none
|
||||
|
||||
wait (vld_out);
|
||||
$display(" cnt_out = %0d (expected 50)", cnt_out);
|
||||
#(CLK_PERIOD*2);
|
||||
disable pulse_gen;
|
||||
|
||||
// --------------------------------------------------
|
||||
// 测试3:脉冲频率 250 kHz (周期 2 us),窗口 1 ms -> 250 个脉冲
|
||||
// --------------------------------------------------
|
||||
$display("Test 3: 250 kHz pulse, window = 1 ms -> expected 250 pulses");
|
||||
fork
|
||||
begin : pulse_gen2
|
||||
forever begin
|
||||
#2us sig_in = 1;
|
||||
#2us sig_in = 0;
|
||||
end
|
||||
end
|
||||
join_none
|
||||
|
||||
wait (vld_out);
|
||||
$display(" cnt_out = %0d (expected 250)", cnt_out);
|
||||
#(CLK_PERIOD*2);
|
||||
disable pulse_gen2;
|
||||
|
||||
// --------------------------------------------------
|
||||
// 测试4:动态改变窗口宽度 (2 ms),脉冲频率 250 kHz
|
||||
// --------------------------------------------------
|
||||
$display("Test 4: 250 kHz pulse, window = 2 ms -> expected 500 pulses");
|
||||
win_us = 24'd2000; // 2 ms
|
||||
|
||||
// 重新启动一个脉冲生成进程
|
||||
fork
|
||||
begin : pulse_gen3
|
||||
forever begin
|
||||
#2us sig_in = 1; // 250 kHz -> 周期 4 us
|
||||
#2us sig_in = 0;
|
||||
end
|
||||
end
|
||||
join_none
|
||||
|
||||
wait (vld_out);
|
||||
$display(" cnt_out = %0d (expected 500)", cnt_out);
|
||||
#(CLK_PERIOD*2);
|
||||
disable pulse_gen3;
|
||||
// --------------------------------------------------
|
||||
// 测试5:边界情况 - 窗口极小 (1 us)
|
||||
// --------------------------------------------------
|
||||
$display("Test 5: 500 kHz pulse, window = 1 us -> expected 0.5? rounded to 0 or 1?");
|
||||
win_us = 24'd2;
|
||||
// 重新启动一个脉冲生成进程
|
||||
fork
|
||||
begin : pulse_gen4
|
||||
forever begin
|
||||
#1us sig_in = 1;
|
||||
#1us sig_in = 0;
|
||||
end
|
||||
end
|
||||
join_none
|
||||
|
||||
wait (vld_out);
|
||||
$display(" cnt_out = %0d (expected 500)", cnt_out);
|
||||
#(CLK_PERIOD*2);
|
||||
disable pulse_gen4;
|
||||
|
||||
// --------------------------------------------------
|
||||
// 测试6:复位过程中行为
|
||||
// --------------------------------------------------
|
||||
$display("Test 6: Assert reset mid-window, check output goes to 0");
|
||||
win_us = 24'd1000;
|
||||
#(500us); // 窗口中间复位
|
||||
rst_n = 0;
|
||||
repeat(5) @(posedge clk);
|
||||
rst_n = 1;
|
||||
wait (vld_out);
|
||||
$display(" cnt_out = %0d (should be fresh measurement)", cnt_out);
|
||||
|
||||
#(10us);
|
||||
$display("Simulation finished.");
|
||||
$finish;
|
||||
end
|
||||
|
||||
// 监控输出有效标志并打印结果
|
||||
always @(posedge vld_out) begin
|
||||
$display("[%t] vld_out asserted, cnt_out = %0d", $time, cnt_out);
|
||||
end
|
||||
|
||||
// 可选:波形转储
|
||||
initial begin
|
||||
$dumpfile("tb_pulse_cnt.vcd");
|
||||
$dumpvars(0, tb_pulse_cnt);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -83,11 +83,11 @@ uart_ctrl_sysreg #(
|
|||
input [31:0] data;
|
||||
begin
|
||||
// 注意:这里发送顺序要和你的串口接收模块端序一致
|
||||
// 假设小端发送:先发 [7:0]
|
||||
send_byte(data[7:0]);
|
||||
send_byte(data[15:8]);
|
||||
send_byte(data[23:16]);
|
||||
// 假设大端发送:先发 [7:0]
|
||||
send_byte(data[31:24]);
|
||||
send_byte(data[23:16]);
|
||||
send_byte(data[15:8]);
|
||||
send_byte(data[7:0]);
|
||||
end
|
||||
endtask
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue