【FPGA】基于ds18b20单总线温度器设计

基于ds18b20单总线温度器设计

一、系统框图 状态转换图

【FPGA】基于ds18b20单总线温度器设计

【FPGA】基于ds18b20单总线温度器设计

二、代码

太久之前写的不想改了直接白嫖的代码
下面展示一些 内联代码片

ds18b20_driver

module ds18b20_driver(
    input               clk          ,
    input               rst_n        ,

    input               dq_in        ,
    output  reg         dq_out       ,
    output  reg         dq_out_en    , 

    output  reg         temp_sign    ,//温度值符号位 0:正 1:负温
    output  reg   [23:0]temp_out     ,
    output  reg         temp_out_vld            
);

//状态机参数

    localparam  M_IDLE = 9'b0_0000_0001,
                M_REST = 9'b0_0000_0010,
                M_RELE = 9'b0_0000_0100,
                M_RACK = 9'b0_0000_1000,
                M_ROMS = 9'b0_0001_0000,
                M_CONT = 9'b0_0010_0000,
                M_WAIT = 9'b0_0100_0000,
                M_RCMD = 9'b0_1000_0000,
                M_RTMP = 9'b1_0000_0000;

    localparam  S_IDLE = 6'b00_0001,
                S_LOW  = 6'b00_0010,
                S_SEND = 6'b00_0100,
                S_SAMP = 6'b00_1000,
                S_RELE = 6'b01_0000,
                S_DONE = 6'b10_0000;

    parameter   TIME_1US  = 50,      //基本时间1us
                TIME_RST  = 480,     //复位脉冲 500us
                TIME_REL  = 20,      //主机释放总线 20us
                TIME_PRE  = 200,     //主机接收存在脉冲 200us
                TIME_WAIT = 750000,  //主机发完温度转换命令 等待750ms
                TIME_LOW  = 2,       //主机拉低总线 2us
                TIME_RW   = 60,      //主机读、写1bit 60us
                TIME_REC  = 2;       //主机读写完1bit释放总线 3us
    
    localparam  CMD_ROMS  = 8'hCC,
                CMD_CONT  = 8'h44,
                CMD_RTMP  = 8'hBE;

//信号定义

    reg     [8:0]       m_state_c   ;//主状态机
    reg     [8:0]       m_state_n   ;

    reg     [5:0]       s_state_c   ;//从状态机
    reg     [5:0]       s_state_n   ;

    reg     [5:0]       cnt_1us     ;//1us计数器
    wire                add_cnt_1us ;
    wire                end_cnt_1us ;

    reg     [19:0]      cnt         ;//复位脉冲、释放、存在脉冲、等待750ms
    wire                add_cnt     ;
    wire                end_cnt     ;
    reg     [19:0]      X           ;

    reg     [4:0]       cnt_bit     ;
    wire                add_cnt_bit ;
    wire                end_cnt_bit ;

    reg                 slave_ack   ;//接收存在脉冲
    reg                 flag        ;//0:发温度转换命令 1:发温度读取命令
    reg     [7:0]       wr_data     ;
    reg     [15:0]      orign_data  ;//采样温度值寄存器  串并转换
    
    reg     [10:0]      temp_data   ;
    wire    [23:0]      temp_data_w ;//组合逻辑计算实际温度值 十进制

    wire                m_idle2m_rest   ;
    wire                m_rest2m_rele   ;
    wire                m_rele2m_rack   ;
    wire                m_rack2m_roms   ;
    wire                m_roms2m_cont   ;
    wire                m_roms2m_rcmd   ;
    wire                m_cont2m_wait   ;
    wire                m_wait2m_rest   ;
    wire                m_rcmd2m_rtmp   ;
    wire                m_rtmp2m_idle   ;

    wire                s_idle2s_low    ;
    wire                s_low2s_send    ;
    wire                s_low2s_samp    ;
    wire                s_send2s_rele   ;
    wire                s_samp2s_rele   ;
    wire                s_rele2s_low    ;
    wire                s_rele2s_done   ;


//状态机设计
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            m_state_c <= M_IDLE;
        end 
        else begin 
            m_state_c <= m_state_n;
        end 
    end

    always @(*)begin 
        case(m_state_c)
            M_IDLE:begin 
                if(m_idle2m_rest)
                    m_state_n = M_REST;
                else 
                    m_state_n = m_state_c;
            end 
            M_REST:begin 
                if(m_rest2m_rele)
                    m_state_n = M_RELE;
                else 
                    m_state_n = m_state_c;
            end
            M_RELE:begin 
                if(m_rele2m_rack)
                    m_state_n = M_RACK;
                else 
                    m_state_n = m_state_c;
            end 
            M_RACK:begin 
                if(m_rack2m_roms)
                    m_state_n = M_ROMS;
                else 
                    m_state_n = m_state_c;
            end 
            M_ROMS:begin 
                if(m_roms2m_cont)
                    m_state_n = M_CONT;
                else if(m_roms2m_rcmd)
                    m_state_n = M_RCMD;
                else 
                    m_state_n = m_state_c;
            end 
            M_CONT:begin 
                if(m_cont2m_wait)
                    m_state_n = M_WAIT;
                else 
                    m_state_n = m_state_c;
            end 
            M_WAIT:begin 
                if(m_wait2m_rest)
                    m_state_n = M_REST;
                else 
                    m_state_n = m_state_c;
            end 
            M_RCMD:begin 
                if(m_rcmd2m_rtmp)
                    m_state_n = M_RTMP;
                else 
                    m_state_n = m_state_c;
            end 
            M_RTMP:begin 
                if(m_rtmp2m_idle)
                    m_state_n = M_IDLE;
                else 
                    m_state_n = m_state_c;
            end         
            default:m_state_n = M_IDLE;
        endcase 
    end

    assign m_idle2m_rest = m_state_c == M_IDLE && (end_cnt_1us);
    assign m_rest2m_rele = m_state_c == M_REST && (end_cnt);
    assign m_rele2m_rack = m_state_c == M_RELE && (end_cnt);
    assign m_rack2m_roms = m_state_c == M_RACK && (end_cnt && slave_ack == 1'b0);
    assign m_roms2m_cont = m_state_c == M_ROMS && (s_state_c == S_DONE && flag == 1'b0);
    assign m_roms2m_rcmd = m_state_c == M_ROMS && (s_state_c == S_DONE && flag == 1'b1);
    assign m_cont2m_wait = m_state_c == M_CONT && (s_state_c == S_DONE);
    assign m_wait2m_rest = m_state_c == M_WAIT && (end_cnt);
    assign m_rcmd2m_rtmp = m_state_c == M_RCMD && (s_state_c == S_DONE);
    assign m_rtmp2m_idle = m_state_c == M_RTMP && (s_state_c == S_DONE);

//从状态机
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            s_state_c <= S_IDLE;
        end 
        else begin 
            s_state_c <= s_state_n;
        end 
    end

    always @(*)begin 
        case(s_state_c)
            S_IDLE:begin 
                if(s_idle2s_low)
                    s_state_n = S_LOW;
                else 
                    s_state_n = s_state_c;
            end  
            S_LOW :begin 
                if(s_low2s_send)
                    s_state_n = S_SEND;
                else if(s_low2s_samp)
                    s_state_n = S_SAMP;
                else 
                    s_state_n = s_state_c;
            end  
            S_SEND:begin 
                if(s_send2s_rele)
                    s_state_n = S_RELE;
                else 
                    s_state_n = s_state_c;
            end  
            S_SAMP:begin 
                if(s_samp2s_rele)
                    s_state_n = S_RELE;
                else 
                    s_state_n = s_state_c;
            end  
            S_RELE:begin 
                if(s_rele2s_done)
                    s_state_n = S_DONE;
                else if(s_rele2s_low)
                    s_state_n = S_LOW;
                else 
                    s_state_n = s_state_c;
            end  
            S_DONE:begin 
                    s_state_n = S_IDLE;
            end  
            default:s_state_n = S_IDLE;
        endcase 
    end

    assign s_idle2s_low  = s_state_c == S_IDLE && (m_state_c == M_ROMS || m_state_c == M_CONT || m_state_c == M_RCMD || m_state_c == M_RTMP);       
    assign s_low2s_send  = s_state_c == S_LOW  && (m_state_c == M_ROMS || m_state_c == M_CONT || m_state_c == M_RCMD) && end_cnt;   
    assign s_low2s_samp  = s_state_c == S_LOW  && (m_state_c == M_RTMP && end_cnt);   
    assign s_send2s_rele = s_state_c == S_SEND && (end_cnt);       
    assign s_samp2s_rele = s_state_c == S_SAMP && (end_cnt);       
    assign s_rele2s_low  = s_state_c == S_RELE && (end_cnt && end_cnt_bit == 1'b0);   
    assign s_rele2s_done = s_state_c == S_RELE && (end_cnt_bit);       

//计数器
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt_1us <= 0;
        end 
        else if(add_cnt_1us)begin 
            if(end_cnt_1us)begin 
                cnt_1us <= 0;
            end
            else begin 
                cnt_1us <= cnt_1us + 1;
            end 
        end
    end 
    assign add_cnt_1us = 1'b1;
    assign end_cnt_1us = add_cnt_1us && cnt_1us == TIME_1US-1;

    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt <= 0;
        end 
        else if(add_cnt)begin 
            if(end_cnt)begin 
                cnt <= 0;
            end
            else begin 
                cnt <= cnt + 1;
            end 
        end
    end 
    assign add_cnt = end_cnt_1us;
    assign end_cnt = add_cnt && cnt == X-1;

    always @(*)begin 
        if(m_state_c == M_REST)begin 
            X = TIME_RST;
        end 
        else if(m_state_c == M_RELE)begin 
            X = TIME_REL;
        end 
        else if(m_state_c == M_RACK)begin 
            X = TIME_PRE;
        end 
        else if(m_state_c == M_WAIT)begin 
            X = TIME_WAIT;
        end
        else begin 
            if(s_state_c == S_LOW)
                X = TIME_LOW;
            else if(s_state_c == S_SEND || s_state_c == S_SAMP)
                X = TIME_RW;
            else 
                X = TIME_REC;
        end 
    end

    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt_bit <= 0;
        end 
        else if(add_cnt_bit)begin 
            if(end_cnt_bit)begin 
                cnt_bit <= 0;
            end
            else begin 
                cnt_bit <= cnt_bit + 1;
            end 
        end
    end 
    assign add_cnt_bit = s_state_c == S_RELE && end_cnt;
    assign end_cnt_bit = add_cnt_bit && cnt_bit == ((m_state_c == M_RTMP)?16-1:8-1);

//slave_ack  采样传感器的存在脉冲
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            slave_ack <= 1'b1;
        end 
        else if(m_state_c == M_RACK && cnt == 60 && end_cnt_1us)begin 
            slave_ack <= dq_in;
        end 
    end

    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            flag <= 0;
        end 
        else if(m_wait2m_rest)begin 
            flag <= 1'b1;
        end 
        else if(m_rtmp2m_idle)begin 
            flag <= 1'b0;
        end 
    end

//输出信号
 
    //dq_out
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            dq_out <= 0;
        end 
        else if(m_idle2m_rest | s_idle2s_low | m_wait2m_rest | s_rele2s_low)begin 
            dq_out <= 1'b0;
        end 
        else if(s_low2s_send)begin 
            dq_out <= wr_data[cnt_bit];
        end 
    end

    //dq_out_en
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            dq_out_en <= 0;
        end 
        else if(m_idle2m_rest | s_idle2s_low | s_rele2s_low | m_wait2m_rest)begin 
            dq_out_en <= 1'b1;      //输出 dq_out
        end 
        else if(m_rest2m_rele | s_send2s_rele | s_low2s_samp)begin 
            dq_out_en <= 1'b0;      //不输出 dq_out
        end 
    end
/*
    注意: 
         在主机发完复位脉冲后要释放总线;
         发完1bit数据后要释放总线;
         在继续发下一bit的时候,仍然要先拉低总线;
         在读数据时,拉低总线1us后要释放总线;
        
*/

//wr_data 
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            wr_data <= 0;
        end 
        else if(m_rack2m_roms)begin 
            wr_data <= CMD_ROMS;
        end 
        else if(m_roms2m_cont)begin 
            wr_data <= CMD_CONT;
        end
        else if(m_roms2m_rcmd)begin 
            wr_data <= CMD_RTMP;
        end 
    end

//orign_data
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            orign_data <= 0;
        end 
        else if(s_state_c == S_SAMP && cnt == 11 && end_cnt_1us)begin 
            orign_data[cnt_bit] <= dq_in; 
        end 
    end

//temp_data
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            temp_data <= 0;
        end 
        else if(s_state_c == S_SAMP && cnt_bit == 15 && s_samp2s_rele)begin 
            if(orign_data[15])
                temp_data <= ~orign_data[10:0] + 1'b1;  //负温 则取反加1 
            else 
                temp_data <= orign_data[10:0];          //正温
        end 
    end

/*
    实际的温度值为 temp_data * 0.0625;
    为了保留4位小数精度,将实际温度值放大了10000倍,
    即 temp_data * 625;

*/
    assign temp_data_w = temp_data * 625;

//temp_out
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            temp_out <= 0;
        end 
        else if(m_state_c == M_RTMP && s_rele2s_done)begin 
            temp_out <= temp_data_w;
        end 
    end

//temp_out_vld
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            temp_out_vld <= 0;
        end 
        else begin 
            temp_out_vld <= m_state_c == M_RTMP && s_rele2s_done;
        end 
    end

//temp_sign
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            temp_sign <= 0;
        end 
        else if(s_state_c == S_SAMP && cnt_bit == 15 && s_samp2s_rele)begin 
            temp_sign <= orign_data[15];
        end 
    end

endmodule


control

module control( 
    input				clk		    ,
    input				rst_n	    ,

    input				din_sign    ,
    input		[23:0]  din		    ,
    input		    	din_vld 	,

    output  wire        dout_sign   ,
    output	wire[23:0]	dout	    ,
    output	reg	    	dout_vld	
);	
             
    //中间信号定义		 
    wire	[23:0]	temp_bcd    ;
    wire            temp_bcd_vld;

	binary2bcd#(.DIN_W(20),.DOUT_W(24))(
    .clk         (clk			),//时钟
    .rst_n       (rst_n			),//复位
    .en          (din_vld		),
    .binary_din  (din[19:0]		),//输入二进制数据
    //输出信号定义
    .bcd_dout    (temp_bcd		),   //输出BCD码数据
    .bcd_dout_vld(temp_bcd_vld	) 
);


    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            dout_vld <= 1'b0;
        end 
        else begin 
            dout_vld <= temp_bcd_vld; 
        end 
    end

    assign dout = temp_bcd;
	assign dout_sign = din_sign;

endmodule

binary2bcd

module binary2bcd#(parameter DIN_W = 32,DOUT_W = 40)(
    input                         clk         ,//时钟
    input                         rst_n       ,//复位
    input                         en          ,
    input          [DIN_W-1:0]    binary_din  ,//输入二进制数据
    //输出信号定义
    output    reg  [DOUT_W-1:0]   bcd_dout    ,   //输出BCD码数据
    output    reg                 bcd_dout_vld 
);

    //状态机参数定义
    localparam  IDLE  = 4'b0001,
                READY = 4'b0010,
                SHIFT = 4'b0100,
                DONE  = 4'b1000;


    //信号定义
    
    reg     [3:0]           state_c      ;
    reg     [3:0]           state_n      ;
    
    reg     [DIN_W-1:0]     din_r        ;      //数据锁存
    reg     [5:0]           shift_cnt    ;      //移位次数计数器
    wire                    add_shift_cnt;
    wire                    end_shift_cnt;

    reg     [3:0]           mem_r0      ;
    reg     [3:0]           mem_r1      ;
    reg     [3:0]           mem_r2      ;
    reg     [3:0]           mem_r3      ;
    reg     [3:0]           mem_r4      ;
    reg     [3:0]           mem_r5      ;
    reg     [3:0]           mem_r6      ;
    reg     [3:0]           mem_r7      ;
    reg     [3:0]           mem_r8      ;
    reg     [3:0]           mem_r9      ;

    wire    [3:0]           mem_w0      ;
    wire    [3:0]           mem_w1      ;
    wire    [3:0]           mem_w2      ;
    wire    [3:0]           mem_w3      ;
    wire    [3:0]           mem_w4      ;
    wire    [3:0]           mem_w5      ;
    wire    [3:0]           mem_w6      ;
    wire    [3:0]           mem_w7      ;
    wire    [3:0]           mem_w8      ;
    wire    [3:0]           mem_w9      ;

    wire    [39:0]          bcd_res     ;
    wire                    idle2ready  ; 
    wire                    shift2done  ;

    always @(posedge clk or negedge rst_n) begin 
        if (!rst_n) begin
            state_c <= IDLE ;
        end
        else begin
            state_c <= state_n;
       end
    end
    
    always @(*) begin 
        case(state_c)  
            IDLE :begin
                if(idle2ready) 
                    state_n = READY;
                else 
                    state_n = state_c;
            end
            READY:begin 
                state_n = SHIFT;
            end 
            SHIFT :begin
                if(shift2done) 
                    state_n = DONE ;
                else 
                    state_n = state_c ;
            end
            DONE :begin
                    state_n = IDLE;
            end
            default : state_n = IDLE;
        endcase
    end
    
    assign idle2ready = state_c == IDLE  && (en);
    assign shift2done = state_c == SHIFT && (end_shift_cnt);

    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            shift_cnt <= 0;
        end
        else if(add_shift_cnt)begin
            if(end_shift_cnt)
                shift_cnt <= 0;
            else
                shift_cnt <= shift_cnt + 1;
        end
    end

    assign add_shift_cnt = state_c == SHIFT;       
    assign end_shift_cnt = add_shift_cnt && shift_cnt == DIN_W-1;   

    //din_r
    always  @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            din_r <= 0;
        end
        else if(en)begin 
            din_r <= binary_din;    
        end 
        else if(state_c == SHIFT)begin    //移位状态下,每个时钟周期向左移1位
            din_r <= din_r << 1'b1;
        end
    end

    always  @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            mem_r0 <= 0;
            mem_r1 <= 0;
            mem_r2 <= 0;
            mem_r3 <= 0;
            mem_r4 <= 0;
            mem_r5 <= 0;
            mem_r6 <= 0;
            mem_r7 <= 0;
            mem_r8 <= 0;
            mem_r9 <= 0;
        end
        else if(idle2ready)begin 
            mem_r0 <= 0;
            mem_r1 <= 0;
            mem_r2 <= 0;
            mem_r3 <= 0;
            mem_r4 <= 0;
            mem_r5 <= 0;
            mem_r6 <= 0;
            mem_r7 <= 0;
            mem_r8 <= 0;
            mem_r9 <= 0;
        end 
        else if(state_c == SHIFT)begin
            mem_r0 <= {mem_w0[2:0],din_r[DIN_W-1]};
            mem_r1 <= {mem_w1[2:0],mem_w0[3]};
            mem_r2 <= {mem_w2[2:0],mem_w1[3]};
            mem_r3 <= {mem_w3[2:0],mem_w2[3]};
            mem_r4 <= {mem_w4[2:0],mem_w3[3]};
            mem_r5 <= {mem_w5[2:0],mem_w4[3]};
            mem_r6 <= {mem_w6[2:0],mem_w5[3]};
            mem_r7 <= {mem_w7[2:0],mem_w6[3]};
            mem_r8 <= {mem_w8[2:0],mem_w7[3]};
            mem_r9 <= {mem_w9[2:0],mem_w8[3]};
        end
    end

    assign mem_w0 = (mem_r0 > 4'd4)?(mem_r0 + 4'd3):mem_r0;
    assign mem_w1 = (mem_r1 > 4'd4)?(mem_r1 + 4'd3):mem_r1;
    assign mem_w2 = (mem_r2 > 4'd4)?(mem_r2 + 4'd3):mem_r2;
    assign mem_w3 = (mem_r3 > 4'd4)?(mem_r3 + 4'd3):mem_r3;
    assign mem_w4 = (mem_r4 > 4'd4)?(mem_r4 + 4'd3):mem_r4;
	assign mem_w5 = (mem_r5 > 4'd4)?(mem_r5 + 4'd3):mem_r5;
    assign mem_w6 = (mem_r6 > 4'd4)?(mem_r6 + 4'd3):mem_r6;
    assign mem_w7 = (mem_r7 > 4'd4)?(mem_r7 + 4'd3):mem_r7;
    assign mem_w8 = (mem_r8 > 4'd4)?(mem_r8 + 4'd3):mem_r8;
    assign mem_w9 = (mem_r9 > 4'd4)?(mem_r9 + 4'd3):mem_r9;

    assign bcd_res = {mem_r9,mem_r8,mem_r7,mem_r6,mem_r5,mem_r4,mem_r3,mem_r2,mem_r1,mem_r0};
    
    always  @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            bcd_dout <= 0;
        end
        else if(state_c == DONE)begin
            bcd_dout <= bcd_res[DOUT_W-1:0];
        end
    end

    always  @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            bcd_dout_vld <= 1'b0;
        end
        else begin
            bcd_dout_vld <= state_c == DONE;
        end
    end

/*
使用4bit二进制数表示0--9

4'b1111 --> 4'd15  0001 0101  8'h15  8'h10 8'h09

8'b10010111   -->  8'd151
		
bcd数					二进制数		左移加3
12'b0000_0000_0000		8'b10010111		初值
12'b0000_0000_0001		8'b00101110		第一次移位
12'b0000_0000_0010		8'b01011100		第二次移位
12'b0000_0000_0100		8'b10111000		第三次移位
12'b0000_0000_1001		8'b01110000		第四次移位
12'b0000_0000_1100		8'b01110000		加3
12'b0000_0001_1000		8'b11100000		第五次移位
12'b0000_0001_1011		8'b11100000		加3
12'b0000_0011_0111		8'b11000000		第六次移位
12'b0000_0011_1010		8'b11000000		加3
12'b0000_0111_0101		8'b10000000		第七次移位
12'b0000_1010_1000		8'b10000000		加3
12'b0001_0101_0001		8'b00000000		第八次移位
*/

endmodule


seg_driver

```javascript
module seg_driver (
    input           clk     ,
    input           rst_n   ,
    input           din_sign,
    input   [23:0]  din     ,
    input           din_vld ,
    output  [5:0]   sel     ,//片选信号
    output  [7:0]   dig      //段选信号
);
    
    parameter TIME_SCAN = 25_000;//扫描间隔 5ms

    localparam  ZER = 7'b100_0000,
                ONE = 7'b111_1001,
                TWO = 7'b010_0100,
                THR = 7'b011_0000,
                FOU = 7'b001_1001,
                FIV = 7'b001_0010,
                SIX = 7'b000_0010,
                SEV = 7'b111_1000,
                EIG = 7'b000_0000,
                NIN = 7'b001_0000,
                N   = 7'b011_1111,//-
                P   = 7'b000_1111;//+

    reg     [19:0]  cnt_scan    ;//数码管扫描计数器
    wire            add_cnt_scan;
    wire            end_cnt_scan;

    reg     [5:0]   seg_sel     ;
    reg     [7:0]   seg_dig     ;
    reg     [3:0]   disp_num    ;
    reg             dot         ;


    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt_scan <= 0;
        end 
        else if(add_cnt_scan)begin 
            if(end_cnt_scan)begin 
                cnt_scan <= 0;
            end
            else begin 
                cnt_scan <= cnt_scan + 1;
            end 
        end
    end 
    assign add_cnt_scan = 1'b1;
    assign end_cnt_scan = add_cnt_scan && cnt_scan == TIME_SCAN-1;

    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            seg_sel <= 6'b111110;
        end 
        else if(end_cnt_scan)begin 
            seg_sel <= {seg_sel[4:0],seg_sel[5]};
        end 
    end

//disp_num
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            disp_num <= 0;
        end 
        else begin 
            case (seg_sel)
                6'b111110:begin disp_num <= din[7:4]  ;dot = 1'b1;end 
                6'b111101:begin disp_num <= din[11:8] ;dot = 1'b1;end 
                6'b111011:begin disp_num <= din[15:12];dot = 1'b1;end 
                6'b110111:begin disp_num <= din[19:16];dot = 1'b0;end 
                6'b101111:begin disp_num <= din[23:20];dot = 1'b1;end 
                6'b011111:begin disp_num <= din_sign?4'ha:4'hb;dot = 1'b1;end 
                default  :begin disp_num <= 4'hF;end 
            endcase
        end 
    end

    //seg_dig
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            seg_dig <= 8'hff;
        end 
        else begin 
            case (disp_num)
                4'h0:seg_dig <= {dot,ZER};
                4'h1:seg_dig <= {dot,ONE};
                4'h2:seg_dig <= {dot,TWO};
                4'h3:seg_dig <= {dot,THR};
                4'h4:seg_dig <= {dot,FOU};
                4'h5:seg_dig <= {dot,FIV};
                4'h6:seg_dig <= {dot,SIX};
                4'h7:seg_dig <= {dot,SEV};
                4'h8:seg_dig <= {dot,EIG};
                4'h9:seg_dig <= {dot,NIN}; 
                4'hA:seg_dig <= {dot,N};
                4'hB:seg_dig <= {dot,P};
                default:seg_dig <= 8'hff;
            endcase
        end 
    end

    assign dig = seg_dig;
    assign sel = seg_sel;

endmodule

temp_detect

```javascript
module temp_detect (
    input               clk     ,
    input               rst_n   ,

    inout               dq      ,//传感器总线

    output      [5:0]   sel     ,
    output      [7:0]   dig     
);

//信号定义

    wire            dq_in       ; 
    wire            dq_out      ; 
    wire            dq_out_en   ; 
    wire            temp_sign   ;   
    wire    [23:0]  temp_out    ;
    wire            temp_out_vld;
    wire    [23:0]  dout        ;
    wire            dout_vld    ;

    assign dq = dq_out_en?dq_out:1'bz;
    assign dq_in = dq;

//模块例化
    ds18b20_driver ds18b20_driver(
        .clk            (clk            ),
        .rst_n          (rst_n          ),
        .dq_in          (dq_in          ),
        .dq_out         (dq_out         ),
        .dq_out_en      (dq_out_en      ),
        .temp_sign      (temp_sign      ), 
        .temp_out       (temp_out       ),
        .temp_out_vld   (temp_out_vld   )           
    );

    control control(
        .clk            (clk            ),
        .rst_n          (rst_n          ),
        .din_sign       (temp_sign      ),
        .din            (temp_out       ),
        .din_vld        (temp_out_vld   ),
        .dout           (dout           ),
        .dout_vld       (dout_vld       )
    );

    seg_driver seg_driver(
        .clk            (clk            ),
        .rst_n          (rst_n          ),
        .din_sign       (temp_sign      ),
        .din            (dout           ),
        .din_vld        (dout_vld       ),
        .sel            (sel            ),
        .dig            (dig            )
    );


    
endmodule

三、验证

【FPGA】基于ds18b20单总线温度器设计

上一篇:redis哨兵模式不会切换


下一篇:Spring学习(一)Spring初识