数字温度传感器

1. DS18B20简介

DS18B20是常用的数字温度传感器,其输出数字信号来表示温度,具有体积小,硬件开发开销低,抗干扰能力强,精度高的特点。

由于封装形式多样,适用于各种狭小空间设备数字测温和控制领域,也可应用于锅炉测温,机房测温,农业大棚测温,洁净室测温,弹药库测温等各种场合。
在这里插入图片描述
DS18B20测量温度范围为-55~+125℃,精度为+/-0.5℃,最大转换时间为750ms。

1.1 命令

DS18B20的命令分为两类,分别是ROM功能命令和RAM功能命令。
ROM功能命令是对64位ROM进行操作:
33H:读ROM
55H:匹配ROM
CCH:跳过ROM
F0H:搜索ROM
ECH:报警搜索命令
如果主机只对一个DS18B20进行操作,就不需要读取ROM编码以及匹配ROM编码,只要用跳过ROM(CCH),就可以进行下一步对高速缓存器的操作。

主机发出对ROM的操作命令之后,就进一步发出对RAM的命令。
在这里插入图片描述
在这里插入图片描述
如果使用寄生电源,总控制器必须在发出温度转换后立即启动强上拉,并保持500ms

1.2 数据格式

在这里插入图片描述
DS18B20在出厂时默认配置温度数据位为12位(补码),其中最高位为符号位。即温度值共11位,最低四位为小数位;低11位的二进制数转化为十进制数后再乘以0.0625得到所测的实际温度值。BYTE1前5位同时变化,前5位均为1时,读取的温度为负值。

1.3 数据时序

主机和从机(DS18B20)间的任何通讯都需要以初始化序列开始:
在这里插入图片描述
每次读写操作至少需要60us,在两次写操作之间至少需要1us的恢复时间;
写操作起始于主机拉低数据总线:
写0:在主机拉低数据线后,保持低电平即可(至少60us);
写1:主机拉低总线(至少1us)后,接着必须在15us之内释放总线
在这里插入图片描述
在写操作开始后15us~60us期间,单总线期间采样总电平状态。
如果在此期间采样值为高电平,则逻辑1写入期间;如果为0,写入逻辑0。

每次读操作至少要60us,在两次读操作期间至少需要1us的恢复时间;
读操作由主机发起,至少拉低总线1us。
在主机发起读操作之后,单总线器件才开始在总线上发送0或1.
若主机发送1,则保持总线为高电平;若发出0,则拉低总线。
在这里插入图片描述
从机发出的数据在其实时隙之后,保持有效时间15us,因此主机在读时隙器件必须释放总线,并且在时隙起始后的15us之内采样总线状态。

DS18B20的典型温度读取过程:
初始化->发跳过ROM命令(CCH)->发温度转换命令(44H)->延时->初始化->发跳过ROM命令(CCH)->发读存储器命令(BEH)->连续读出两个字节温度数据->结束或开始下一循环。

2. 程序设计

使用FOGA开发板通过DS18B20采集温度,并将采集的温度值(带符号位)用数码管显示。
系统框图
在这里插入图片描述
代码

module temp_disp(
    input            sys_clk     ,    //输入的系统时钟
    input            sys_rst_n   ,    //输入的复位信号
    inout            dq          ,    //ds18b20温度传感器单总线
    output  [5:0]    sel         ,    //输出数码管位选信号
    output  [7:0]    seg_led          //输出数码管段选信号
);

//parameter define
parameter POINT = 6'b000100;          // 数码管小数点的位置

//wire define
wire    [19:0]  temp_data;            // 温度数值
wire            sign;                 // 符号位

//*****************************************************
//**                    main code
//*****************************************************

//例化动态数码管驱动模块
seg_led u_seg_led(
    //module clock
    .clk           (sys_clk  ),       // 时钟信号
    .rst_n         (sys_rst_n),       // 复位信号
    //seg_led interface
    .seg_sel       (sel      ),       // 位选
    .seg_led       (seg_led  ),       // 段选
    //user interface
    .data          (temp_data),       // 显示的数值
    .point         (POINT    ),       // 小数点具体显示的位置,从高到低,高电平有效
    .en            (1'b1     ),       // 数码管使能信号
    .sign          (sign     )        // 符号位(高电平显示“-”号)
);

//例化DS18B20驱动模块
ds18b20_dri u1_ds18b20_dri(
    //module clock
    .clk          (sys_clk  ),        // 时钟信号(50MHz)
    .rst_n        (sys_rst_n),        // 复位信号
    //user interface
    .dq           (dq       ),        // DS18B20的DQ引脚数据
    .temp_data    (temp_data),        // 转换后得到的温度值
    .sign         (sign     )         // 符号位
);

endmodule
module ds18b20_dri(
    //module clock
    input              clk        ,         // 时钟信号(50MHz)
    input              rst_n      ,         // 复位信号

    //user interface
    inout              dq         ,         // DS18B20的DQ引脚数据
    output reg [19:0]  temp_data  ,         // 转换后得到的温度值
    output reg         sign                 // 符号位
);

//parameter define
localparam  ROM_SKIP_CMD = 8'hcc;           // 跳过 ROM 命令
localparam  CONVERT_CMD  = 8'h44;           // 温度转换命令
localparam  READ_TEMP    = 8'hbe;           // 读 DS1820 温度暂存器命令
//state define
localparam  init         = 3'd1 ;           // 初始化状态
localparam  rom_skip     = 3'd2 ;           // 加载跳过ROM命令
localparam  wr_byte      = 3'd3 ;           // 写字节状态
localparam  temp_convert = 3'd4 ;           // 加载温度转换命令
localparam  delay        = 3'd5 ;           // 延时等待温度转换结束
localparam  rd_temp      = 3'd6 ;           // 加载读温度命令
localparam  rd_byte      = 3'd7 ;           // 读字节状态

//reg define
reg     [ 4:0]         cnt         ;        // 分频计数器
reg                    clk_1us     ;        // 1MHz时钟
reg     [19:0]         cnt_1us     ;        // 微秒计数
reg     [ 2:0]         cur_state   ;        // 当前状态
reg     [ 2:0]         next_state  ;        // 下一状态
reg     [ 3:0]         flow_cnt    ;        // 流转计数
reg     [ 3:0]         wr_cnt      ;        // 写计数
reg     [ 4:0]         rd_cnt      ;        // 读计数
reg     [ 7:0]         wr_data     ;        // 写入DS18B20的数据
reg     [ 4:0]         bit_width   ;        // 读取的数据的位宽
reg     [15:0]         rd_data     ;        // 采集到的数据
reg     [15:0]         org_data    ;        // 读取到的原始温度数据
reg     [10:0]         data1       ;        // 对原理温度进行符号处理
reg     [ 3:0]         cmd_cnt     ;        // 发送命令计数
reg                    init_done   ;        // 初始化完成信号
reg                    st_done     ;        // 完成信号
reg                    cnt_1us_en  ;        // 使能计时
reg                    dq_out      ;        // DS18B20的dq输出

//wire define
wire    [19:0]         data2       ;        // 对处理后的进行转换处理

//*****************************************************
//**                    main code
//*****************************************************

assign dq = dq_out;

//分频生成1MHz的时钟信号
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt     <= 5'b0;
        clk_1us <= 1'b0;
    end
    else if(cnt < 5'd24) begin
        cnt     <= cnt + 1'b1;
        clk_1us <= clk_1us;
    end
    else begin
        cnt     <= 5'b0;
        clk_1us <= ~clk_1us;
    end
end

//微秒计时
always @ (posedge clk_1us or negedge rst_n) begin
    if (!rst_n)
        cnt_1us <= 20'b0;
    else if (cnt_1us_en)
        cnt_1us <= cnt_1us + 1'b1;
    else
        cnt_1us <= 20'b0;
end

//状态跳转
always @ (posedge clk_1us or negedge rst_n) begin
    if(!rst_n)
        cur_state <= init;
    else 
        cur_state <= next_state;
end

//组合逻辑状态判断转换条件
always @( * ) begin
    case(cur_state)
        init: begin                             // 初始化状态
            if (init_done)
                next_state = rom_skip;
            else
                next_state = init;
        end
        rom_skip: begin                         // 加载跳过ROM命令
            if(st_done)
                next_state = wr_byte;
            else
                next_state = rom_skip;
        end
        wr_byte: begin                          // 发送命令
            if(st_done)
                case(cmd_cnt)                   // 根据命令序号,判断下个状态
                    4'b1: next_state = temp_convert;
                    4'd2: next_state = delay;
                    4'd3: next_state = rd_temp;
                    4'd4: next_state = rd_byte;
                    default: 
					      next_state = temp_convert;
                endcase
            else
                next_state = wr_byte;
        end
        temp_convert: begin                     // 加载温度转换命令
            if(st_done)
                next_state = wr_byte;
            else
                next_state = temp_convert;
        end
        delay: begin                            // 延时等待温度转换结束
            if(st_done)
                next_state = init;
            else
                next_state = delay;
        end
        rd_temp: begin                          // 加载读温度命令
            if(st_done)
                next_state = wr_byte;
            else
                next_state = rd_temp;
        end
        rd_byte: begin                          // 读数据线上的数据
            if(st_done)
                next_state = init;
            else
                next_state = rd_byte;
        end
        default: next_state = init;
    endcase
end

//整个操作步骤为初始化、发送跳过ROM操作命令、发送温度转换指令、
//再初始化、再发送跳过ROM操作指令、发送读数据指令。
always @ (posedge clk_1us or negedge rst_n) begin
    if(!rst_n) begin
        flow_cnt     <=  4'b0;
        init_done    <=  1'b0;
        cnt_1us_en   <=  1'b1;
        dq_out       <=  1'bZ;
        st_done      <=  1'b0;
        rd_data      <= 16'b0;
        rd_cnt       <=  5'd0;
        wr_cnt       <=  4'd0;
        cmd_cnt      <=  3'd0;
    end
    else begin
        st_done <= 1'b0;
        case (next_state)
            init:begin                              //初始化
                init_done <= 1'b0;
                case(flow_cnt)
                    4'd0:
						flow_cnt <= flow_cnt + 1'b1;
						4'd1: begin					//发出500us复位脉冲
                        cnt_1us_en <= 1'b1;         
                        if(cnt_1us < 20'd500)
                            dq_out <= 1'b0;         
                        else begin
                            cnt_1us_en <= 1'b0;
                            dq_out <= 1'bz;
                            flow_cnt <= flow_cnt + 1'b1;
                        end
                    end
                    4'd2:begin						//释放总线,等待30us
                        cnt_1us_en <= 1'b1;
                        if(cnt_1us < 20'd30)
                            dq_out <= 1'bz;
                        else
                            flow_cnt <= flow_cnt + 1'b1;
                    end
                    4'd3: begin						//检测响应信号
                        if(!dq)
                            flow_cnt <= flow_cnt + 1'b1;
                        else
                            flow_cnt <= flow_cnt;
                    end
                    4'd4: begin						//等待初始化结束
                        if(cnt_1us == 20'd500) begin
                            cnt_1us_en <= 1'b0;
                            init_done  <= 1'b1;		//初始化完成
                            flow_cnt   <= 4'd0;
                        end
                        else
                            flow_cnt <= flow_cnt;
                    end
                    default: flow_cnt <= 4'd0;
                endcase
            end
            rom_skip: begin                         //加载跳过ROM操作指令
                wr_data  <= ROM_SKIP_CMD;
                flow_cnt <= 4'd0;
                st_done  <= 1'b1;
            end
            wr_byte: begin                          //写字节状态(发送指令)
                if(wr_cnt <= 4'd7) begin
                    case (flow_cnt)
                        4'd0: begin
                            dq_out <= 1'b0;			//拉低数据线,开始写操作
                            cnt_1us_en <= 1'b1;		//启动计时器
                            flow_cnt <= flow_cnt + 1'b1;
                        end
                        4'd1: begin					//数据线拉低1us
                            flow_cnt <= flow_cnt + 1'b1;
                        end
                        4'd2: begin
                            if(cnt_1us < 20'd60)	//发送数据
                                dq_out <= wr_data[wr_cnt];
                            else if(cnt_1us < 20'd63) 	
                                dq_out <= 1'bz;		//释放总线(发送间隔)
                            else
                                flow_cnt <= flow_cnt + 1'b1;
                        end
                        4'd3: begin					//发送1位数据完成
                            flow_cnt <= 0;
                            cnt_1us_en <= 1'b0;
                            wr_cnt <= wr_cnt + 1'b1;//写计数器加1
                        end
                        default : flow_cnt <= 0;
                    endcase
                end
                else begin							//发送指令(1Byte)结束
                    st_done <= 1'b1;
                    wr_cnt <= 4'b0;
                    cmd_cnt <= (cmd_cnt == 3'd4) ?  //标记当前发送的指令序号
					           3'd1 : (cmd_cnt+ 1'b1);
                end
            end
            temp_convert: begin                     //加载温度转换命令
                wr_data <= CONVERT_CMD;
                st_done <= 1'b1;
            end
            delay: begin                            //延时500ms等待温度转换结束
                cnt_1us_en <= 1'b1;
                if(cnt_1us == 20'd500000) begin
                    st_done <= 1'b1;
                    cnt_1us_en <= 1'b0;
                end 
            end 
            rd_temp: begin                          //加载读温度命令
                wr_data <= READ_TEMP;
                bit_width <= 5'd16;					//指定读数据个数
                st_done <= 1'b1;
            end
            rd_byte: begin                          //接收16位温度数据
                if(rd_cnt < bit_width) begin
                    case(flow_cnt)
                        4'd0: begin
                            cnt_1us_en <= 1'b1;
                            dq_out <= 1'b0;			//拉低数据线,开始读操作
                            flow_cnt <= flow_cnt + 1'b1;
                        end
                        4'd1: begin
                            dq_out <= 1'bz;			//释放总线并在15us内接收数据
                            if(cnt_1us == 20'd14) begin
                                rd_data <= {
    
    dq,rd_data[15:1]};
                                flow_cnt <= flow_cnt + 1'b1 ;
                            end
                        end
                        4'd2: begin
                            if (cnt_1us <= 20'd64)	//读1位数据结束
                                dq_out <= 1'bz;
                            else begin
                                flow_cnt <= 4'd0;	
                                rd_cnt <= rd_cnt + 1'b1;//读计数器加1
                                cnt_1us_en <= 1'b0;
                            end
                        end
                        default : flow_cnt <= 4'd0;
                    endcase
                end
                else begin
                    st_done <= 1'b1;
                    org_data  <= rd_data;
                    rd_cnt <= 5'b0;
                end
            end
            default: ;
        endcase
    end 
end

//判断符号位
always @(posedge clk_1us or negedge rst_n) begin
    if(!rst_n) begin
        sign  <=  1'b0;
        data1 <= 11'b0;
    end
    else if(org_data[15] == 1'b0) begin
        sign  <= 1'b0;
        data1 <= org_data[10:0];
    end
    else if(org_data[15] == 1'b1) begin
        sign  <= 1'b1;
        data1 <= ~org_data[10:0] + 1'b1;
    end
end

//对采集到的温度进行转换
assign data2 = (data1 * 11'd625)/ 7'd100;

//温度输出
always @(posedge clk_1us or negedge rst_n) begin
    if(!rst_n)
        temp_data <= 20'b0;
    else
        temp_data <= data2;
end

endmodule
module seg_led(
    input                   clk    ,        // 时钟信号
    input                   rst_n  ,        // 复位信号

    input         [19:0]    data   ,        // 6位数码管要显示的数值
    input         [5:0]     point  ,        // 小数点具体显示的位置,从高到低,高电平有效
    input                   en     ,        // 数码管使能信号
    input                   sign   ,        // 符号位(高电平显示“-”号)

    output   reg  [5:0]     seg_sel,        // 数码管位选,最左侧数码管为最高位
    output   reg  [7:0]     seg_led         // 数码管段选
    );

//parameter define
localparam  CLK_DIVIDE = 4'd10     ;        // 时钟分频系数
localparam  MAX_NUM    = 13'd5000  ;        // 对数码管驱动时钟(5MHz)计数1ms所需的计数值

//reg define
reg    [ 3:0]             clk_cnt  ;        // 时钟分频计数器
reg                       dri_clk  ;        // 数码管的驱动时钟,5MHz
reg    [23:0]             num      ;        // 24位bcd码寄存器
reg    [12:0]             cnt0     ;        // 数码管驱动时钟计数器
reg                       flag     ;        // 标志信号(标志着cnt0计数达1ms)
reg    [2:0]              cnt_sel  ;        // 数码管位选计数器
reg    [3:0]              num_disp ;        // 当前数码管显示的数据
reg                       dot_disp ;        // 当前数码管显示的小数点

//wire define
wire   [3:0]              data0    ;        // 个位数
wire   [3:0]              data1    ;        // 十位数
wire   [3:0]              data2    ;        // 百位数
wire   [3:0]              data3    ;        // 千位数
wire   [3:0]              data4    ;        // 万位数
wire   [3:0]              data5    ;        // 十万位数

//*****************************************************
//**                    main code
//*****************************************************

//提取显示数值所对应的十进制数的各个位
assign  data0 = data % 4'd10;               // 个位数
assign  data1 = data / 4'd10 % 4'd10   ;    // 十位数
assign  data2 = data / 7'd100 % 4'd10  ;    // 百位数
assign  data3 = data / 10'd1000 % 4'd10 ;   // 千位数
assign  data4 = data / 14'd10000 % 4'd10;   // 万位数
assign  data5 = data / 17'd100000;          // 十万位数

//对系统时钟10分频,得到的频率为5MHz的数码管驱动时钟dri_clk
always @(posedge clk or negedge rst_n) begin
   if(!rst_n) begin
       clk_cnt <= 4'd0;
       dri_clk <= 1'b1;
   end
   else if(clk_cnt == CLK_DIVIDE/2 - 1'd1) begin
       clk_cnt <= 4'd0;
       dri_clk <= ~dri_clk;
   end
   else begin
       clk_cnt <= clk_cnt + 1'b1;
       dri_clk <= dri_clk;
   end
end

//将20位2进制数转换为8421bcd码(即使用4位二进制数表示1位十进制数)
always @ (posedge dri_clk or negedge rst_n) begin
    if (!rst_n)
        num <= 24'b0;
    else begin
        if (data5 || point[5]) begin     //如果显示数据为6位十进制数,
            num[23:20] <= data5;         //则依次给6位数码管赋值
            num[19:16] <= data4;
            num[15:12] <= data3;
            num[11:8]  <= data2;
            num[ 7:4]  <= data1;
            num[ 3:0]  <= data0;
        end
        else begin                         
            if (data4 || point[4]) begin //如果显示数据为5位十进制数,则给低5位数码管赋值
                num[19:0] <= {
    
    data4,data3,data2,data1,data0};
                if(sign)                    
                    num[23:20] <= 4'd11; //如果需要显示负号,则最高位(第6位)为符号位
                else
                    num[23:20] <= 4'd10; //不需要显示负号时,则第6位不显示任何字符
            end
            else begin                   //如果显示数据为4位十进制数,则给低4位数码管赋值
                if (data3 || point[3]) begin
                    num[15: 0] <= {
    
    data3,data2,data1,data0};
                    num[23:20] <= 4'd10; //第6位不显示任何字符
                    if(sign)             //如果需要显示负号,则最高位(第5位)为符号位
                        num[19:16] <= 4'd11;
                    else                 //不需要显示负号时,则第5位不显示任何字符
                        num[19:16] <= 4'd10;
                end
                else begin               //如果显示数据为3位十进制数,则给低3位数码管赋值
                    if (data2 || point[2]) begin
                        num[11: 0] <= {
    
    data2,data1,data0};
                                         //第6、5位不显示任何字符
                        num[23:16] <= {
    
    2{
    
    4'd10}};
                        if(sign)         //如果需要显示负号,则最高位(第4位)为符号位
                            num[15:12] <= 4'd11;
                        else             //不需要显示负号时,则第4位不显示任何字符
                            num[15:12] <= 4'd10;
                    end
                    else begin           //如果显示数据为2位十进制数,则给低2位数码管赋值
                        if (data1 || point[1]) begin
                            num[ 7: 0] <= {
    
    data1,data0};
                                         //第6、5、4位不显示任何字符
                            num[23:12] <= {
    
    3{
    
    4'd10}};
                            if(sign)     //如果需要显示负号,则最高位(第3位)为符号位
                                num[11:8]  <= 4'd11;
                            else         //不需要显示负号时,则第3位不显示任何字符
                                num[11:8] <=  4'd10;
                        end
                        else begin       //如果显示数据为1位十进制数,则给最低位数码管赋值
                            num[3:0] <= data0;
                                         //第6、5位不显示任何字符
                            num[23:8] <= {
    
    4{
    
    4'd10}};
                            if(sign)     //如果需要显示负号,则最高位(第2位)为符号位
                                num[7:4] <= 4'd11;
                            else         //不需要显示负号时,则第2位不显示任何字符
                                num[7:4] <= 4'd10;
                        end
                    end
                end
            end
        end
    end
end

//每当计数器对数码管驱动时钟计数时间达1ms,输出一个时钟周期的脉冲信号
always @ (posedge dri_clk or negedge rst_n) begin
    if (rst_n == 1'b0) begin
        cnt0 <= 13'b0;
        flag <= 1'b0;
     end
    else if (cnt0 < MAX_NUM - 1'b1) begin
        cnt0 <= cnt0 + 1'b1;
        flag <= 1'b0;
     end
    else begin
        cnt0 <= 13'b0;
        flag <= 1'b1;
     end
end

//cnt_sel从0计数到5,用于选择当前处于显示状态的数码管
always @ (posedge dri_clk or negedge rst_n) begin
    if (rst_n == 1'b0)
        cnt_sel <= 3'b0;
    else if(flag) begin
        if(cnt_sel < 3'd5)
            cnt_sel <= cnt_sel + 1'b1;
        else
            cnt_sel <= 3'b0;
    end
    else
        cnt_sel <= cnt_sel;
end

//控制数码管位选信号,使6位数码管轮流显示
always @ (posedge dri_clk or negedge rst_n) begin
    if(!rst_n) begin
        seg_sel  <= 6'b111111;              //位选信号低电平有效
        num_disp <= 4'b0;           
        dot_disp <= 1'b1;                   //共阳极数码管,低电平导通
    end
    else begin
        if(en) begin
            case (cnt_sel)
                3'd0 :begin
                    seg_sel  <= 6'b111110;  //显示数码管最低位
                    num_disp <= num[3:0] ;  //显示的数据
                    dot_disp <= ~point[0];  //显示的小数点
                end
                3'd1 :begin
                    seg_sel  <= 6'b111101;  //显示数码管第1位
                    num_disp <= num[7:4] ;
                    dot_disp <= ~point[1];
                end
                3'd2 :begin
                    seg_sel  <= 6'b111011;  //显示数码管第2位
                    num_disp <= num[11:8];
                    dot_disp <= ~point[2];
                end
                3'd3 :begin
                    seg_sel  <= 6'b110111;  //显示数码管第3位
                    num_disp <= num[15:12];
                    dot_disp <= ~point[3];
                end
                3'd4 :begin
                    seg_sel  <= 6'b101111;  //显示数码管第4位
                    num_disp <= num[19:16];
                    dot_disp <= ~point[4];
                end
                3'd5 :begin
                    seg_sel  <= 6'b011111;  //显示数码管最高位
                    num_disp <= num[23:20];
                    dot_disp <= ~point[5];
                end
                default :begin
                    seg_sel  <= 6'b111111;
                    num_disp <= 4'b0;
                    dot_disp <= 1'b1;
                end
            endcase
        end
        else begin
            seg_sel  <= 6'b111111;          //使能信号为0时,所有数码管均不显示
            num_disp <= 4'b0;
            dot_disp <= 1'b1;
        end
    end
end

//控制数码管段选信号,显示字符
always @ (posedge dri_clk or negedge rst_n) begin
    if (!rst_n)
        seg_led <= 8'hc0;
    else begin
        case (num_disp)
            4'd0 : seg_led <= {dot_disp,7'b1000000}; //显示数字 0
            4'd1 : seg_led <= {dot_disp,7'b1111001}; //显示数字 1
            4'd2 : seg_led <= {dot_disp,7'b0100100}; //显示数字 2
            4'd3 : seg_led <= {dot_disp,7'b0110000}; //显示数字 3
            4'd4 : seg_led <= {dot_disp,7'b0011001}; //显示数字 4
            4'd5 : seg_led <= {dot_disp,7'b0010010}; //显示数字 5
            4'd6 : seg_led <= {dot_disp,7'b0000010}; //显示数字 6
            4'd7 : seg_led <= {dot_disp,7'b1111000}; //显示数字 7
            4'd8 : seg_led <= {dot_disp,7'b0000000}; //显示数字 8
            4'd9 : seg_led <= {dot_disp,7'b0010000}; //显示数字 9
            4'd10: seg_led <= 8'b11111111;           //不显示任何字符
            4'd11: seg_led <= 8'b10111111;           //显示负号(-)
            default: 
                   seg_led <= {
    
    dot_disp,7'b1000000};
        endcase
    end
end

endmodule 

猜你喜欢

转载自blog.csdn.net/gemengxia/article/details/115402329