`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