Verilog的6位,8位数码管译码

module seg_7(
                input clk,
                input rst_n,
                input [23:0]data_in,
                output reg [2:0]sel,
                output reg [7:0]seg
                );

    parameter CNT_1K = 15'd24999;//分频计数

    reg [3:0]data_tmp;//译码数据缓存
    reg [14:0]cnt_1k;
    reg flag_1K;

    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt_1k <= 15'd0;
    else if(cnt_1k == CNT_1K)
        cnt_1k <= 15'd0;
    else
        cnt_1k <= cnt_1k + 1'b1;

    //1K扫描时钟生成模块        
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        flag_1K <= 1'b0;
    else if(cnt_1k == CNT_1K)
        flag_1K <= 1'b1;  //产生1K扫描时钟的脉冲信号
    else
        flag_1K <= 1'b0;

    //6位循环移位寄存器
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        sel <= 3'd0;
    else if(sel == 3'd5&&flag_1K==1'b1)//
        sel <= 3'd0;
    else if(flag_1K==1'b1)
        sel <=  sel + 1'b1;

    always@(posedge clk or negedge rst_n)
    if(!rst_n)
            data_tmp <= 4'd0;
    else begin
        case(sel)//数码管位选选择
            3'd0:data_tmp <= data_in[23:20];
            3'd1:data_tmp <= data_in[19:16];
            3'd2:data_tmp <= data_in[15:12];
            3'd3:data_tmp <= data_in[11:8];
            3'd4:data_tmp <= data_in[7:4];
            3'd5:data_tmp <= data_in[3:0];
            default:data_tmp <= 4'd0;
        endcase
    end

    always@(posedge clk or negedge rst_n)
    if(!rst_n)
        seg <= 8'b01000000;
    else begin
        case(data_tmp)//译码显示值
            4'h0    :   seg <= 8'b11000000; //0
            4'h1    :   seg <= 8'b11111001; //1
            4'h2    :   seg <= 8'b10100100; //2
            4'h3    :   seg <= 8'b10110000; //3
            4'h4    :   seg <= 8'b10011001; //4
            4'h5    :   seg <= 8'b10010010; //5
            4'h6    :   seg <= 8'b10000010; //6
            4'h7    :   seg <= 8'b11111000; //7
            4'h8    :   seg <= 8'b10000000; //8
            4'h9    :   seg <= 8'b10010000; //9
            4'ha    :   seg <= 8'b10001000; //a
            4'hb    :   seg <= 8'b10000011; //b
            4'hc    :   seg <= 8'b10000110; //c
            4'hd    :   seg <= 8'b10100001; //d
            4'he    :   seg <= 8'b10000110; //e
            4'hf    :   seg <= 8'b10001110; //f
        endcase
    end
endmodule

//代码解释
产生Flag_1K扫描时钟脉冲,在高速电路中,需要分频时钟可以使用PLL,或者产生分频脉冲作为触发信号

建议当代码中多次使用变量的时候使用parameter CNT_1K = 15’d24999;这样修改代码时,不需要到代码中一个个修改了,直接修改参数中的数值即可

//了解参数化使用以及优点请点击

切记:所有的always(posedge clk or negedge rst_n)要基于系统时钟
避免时序分析的时候报错


附:8位数码管译码

原理同6位数码管

注意:
此代码使用的经过修改直接分频时钟clk_1K作为触发信号作为对比
因为数码管电路不要求高速,直接使用分频信号影响不大,但建议养成良好的习惯
比如使用 `define Char_0 7’b1000000 //字符 ‘0’

    `define Char_0  7'b1000000  //字符 ‘0’
    `define Char_1  7'b1111001  //字符 ‘1’
    `define Char_2  7'b0100100  //字符 ‘2’
    `define Char_3  7'b0110000  //字符 ‘3’
    `define Char_4  7'b0011001  //字符 ‘4’
    `define Char_5  7'b0010010  //字符 ‘5’
    `define Char_6  7'b0000010  //字符 ‘6’
    `define Char_7  7'b1111000  //字符 ‘7’
    `define Char_8  7'b0000000  //字符 ‘8’
    `define Char_9  7'b0010000  //字符 ‘9’
    `define Char_a  7'b0001000  //字符 ‘A’
    `define Char_b  7'b0000011  //字符 ‘b’
    `define Char_c  7'b1000110  //字符 ‘C’
    `define Char_d  7'b0100001  //字符 ‘d’
    `define Char_e  7'b0000110  //字符 ‘E’
    `define Char_f  7'b0001110  //字符 ‘F’

    `define Char__  7'b0111111  //字符 ‘-’
    `define Char_H  7'b0001001  //字符 ‘H’
    `define Char_OFF 7'b1111111  //消影

    reg [14:0]divider_cnt;//25000-1

    reg clk_1K;
    reg [7:0]sel_r;

    reg [3:0]data_tmp;//数据缓存

//  分频计数器计数模块
    always@(posedge Clk or negedge Rst_n)
    if(!Rst_n)
        divider_cnt <= 15'd0;
    else if(!En)
        divider_cnt <= 15'd0;
    else if(divider_cnt == 24999)
        divider_cnt <= 15'd0;
    else
        divider_cnt <= divider_cnt + 1'b1;

//1K扫描时钟生成模块        
    always@(posedge Clk or negedge Rst_n)
    if(!Rst_n)
        clk_1K <= 1'b0;
    else if(divider_cnt == 24999)
        clk_1K <= ~clk_1K;
    else
        clk_1K <= clk_1K;

//8位循环移位寄存器
//此处clk_1K 正确方式应该使用脉冲触发
    always@(posedge clk_1K or negedge Rst_n)
    if(!Rst_n)
        sel_r <= 8'b0000_0001;
    else if(sel_r == 8'b1000_0000 || 8'b0000_0000)
        sel_r <= 8'b0000_0001;
    else
        sel_r <=  sel_r << 1;

//数据多路器,根据当前扫描的数码管位,将对于数据传给显示暂存
    always@(*)
        case(sel_r)
            8'b0000_0001:data_tmp = disp_data[3:0];
            8'b0000_0010:data_tmp = disp_data[7:4];
            8'b0000_0100:data_tmp = disp_data[11:8];
            8'b0000_1000:data_tmp = disp_data[15:12];
            8'b0001_0000:data_tmp = disp_data[19:16];
            8'b0010_0000:data_tmp = disp_data[23:20];
            8'b0100_0000:data_tmp = disp_data[27:24];
            8'b1000_0000:data_tmp = disp_data[31:28];
            default:data_tmp = 4'b0000;
        endcase

//对显示暂存内容进行译码,并输出该数据对应的段码       
    always@(*)
        case(data_tmp)
            4'h0:seg = `Char_0; //字符 ‘04'h1:seg = `Char_1; //字符 ‘14'h2:seg = `Char_2; //字符 ‘24'h3:seg = `Char_3; //字符 ‘34'h4:seg = `Char_4; //字符 ‘44'h5:seg = `Char_5; //字符 ‘54'h6:seg = `Char_6; //字符 ‘64'h7:seg = `Char_7; //字符 ‘74'h8:seg = `Char_8; //字符 ‘84'h9:seg = `Char_9; //字符 ‘94'ha:seg = `Char_a; //字符 ‘A’
            4'hb:seg = `Char__; //字符 ‘-’
            4'hc:seg = `Char_c; //字符 ‘C’
            4'hd:seg = `Char_OFF; //消影
            4'he:seg = `Char_H; //字符 ‘H’
            4'hf:seg = `Char_f; //字符 ‘F’    
        endcase

//根据是否使能数码管显示,控制位选值     
    assign sel = (En)?sel_r:8'b0000_0000;

你可能感兴趣的:(精品代码模块)