ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-02-28 20:06:30  阅读:194  来源: 互联网

标签:wire 0000 temp FPGA ds18b20 mem 单总线 rst reg


基于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

三、验证

在这里插入图片描述

标签:wire,0000,temp,FPGA,ds18b20,mem,单总线,rst,reg
来源: https://blog.csdn.net/li_lys/article/details/123190259

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有