94 lines
3.0 KiB
Verilog
94 lines
3.0 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
|
|
wire [23:0] cur_freq_khz;
|
|
reg signed [23:0] temp_scaled;
|
|
|
|
assign cur_freq_khz = (wd_cnt_out * 1000) / win_us;
|
|
//Scale temperature result by 100 times
|
|
always @(posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
temp_scaled <= 0;
|
|
end else if (wd_cnt_vld) begin
|
|
//If current frequency <= calibrated frequency at -40¡ãC, output -4000 directly
|
|
if (cur_freq_khz <= temp_neg_40_fre_k) begin
|
|
temp_scaled <= -32'sd4000;
|
|
end
|
|
else begin
|
|
//Calculate interpolation only when frequency > lower limit to avoid subtraction overflow
|
|
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 |