digital_therm已经修改仿真完了没问题了,uart_ctrl也没问题

This commit is contained in:
yangshenbo 2026-04-05 18:22:33 +08:00
parent 81852b1579
commit c38356bc50
2 changed files with 241 additions and 58 deletions

View File

@ -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;
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;
//映射表
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;
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~130050.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

View File

@ -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