thermometer_digital/uart_thermometer_digital/rtl/therm/digital_thermometer.v

95 lines
2.8 KiB
Verilog

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Yangshenbo
// version:V1.0
// Create Date: 2026/04/05
//////////////////////////////////////////////////////////////////////////////////
module digital_thermometer(
input clk,
input rst_n,
input sig_in,
input [23:0]win_us,
input [1:0]out_mode, //0: output temperature, 1: output frequency, 2: output pulse count per window
input [15:0]temp_85_fre_k, //Frequency at 85¡ãC, default 600khz
input [15:0]temp_neg_40_fre_k , //Frequency at -40¡ãC, default 160khz, unit khz
input report_en, //Auto report enable
input [23:0]rep_gap_us, //Minimum report gap (us)
output reg [23:0]therm_out,
output reg therm_vld
);
wire [23:0] wd_cnt_out;
wire wd_cnt_vld;
reg [23:0] gap_cnt; // Report interval counter
reg [23:0] cur_freq_khz;
reg signed [23:0] temp_scaled;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cur_freq_khz <= 0;
temp_scaled <= 0;
end
else begin
cur_freq_khz <= (wd_cnt_out * 1000) / win_us;
if (cur_freq_khz <= temp_neg_40_fre_k) begin
temp_scaled <= -32'sd4000;
end
else begin
temp_scaled <= ((cur_freq_khz - temp_neg_40_fre_k) * 12500) / (temp_85_fre_k - temp_neg_40_fre_k) - 4000;
end
end
end
// Report logic and output selection
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
//Output mode switching
case (out_mode)
2'd0: therm_out <= temp_scaled; //Output temperature scaled by 100
2'd1: therm_out <= cur_freq_khz; //Output frequency (kHz)
2'd2: therm_out <= wd_cnt_out; //Output raw pulse count
default: therm_out <= temp_scaled;
endcase
end
else begin
therm_vld <= 1'b0;
end
end
//Instantiate sub-module
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