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;
  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现LDPC译码需要以下步骤: 1. 确定LDPC码的参数,包括码长、信息数、校验数、校验矩阵等。 2. 实现译码算法,常用的算法有Min-Sum算法、Belief-Propagation算法等。 3. 在Verilog中实现译码算法,包括计算校验节点的值、更新信息节点的值等。 4. 设计测试程序,对实现的LDPC译码器进行验证。 下面是一个简单的LDPC译码器的Verilog代码实现,使用Min-Sum算法: ``` module ldpc_decoder( input clk, input rst_n, input [N-1:0] rx_data, output [K-1:0] tx_data ); parameter N = 128; parameter K = 64; parameter M = 64; parameter ITER_NUM = 10; // 校验矩阵H reg [M-1:0] H[M][N]; // 信息节点的值 reg [K-1:0] l[K]; // 校验节点的值 reg [M-1:0] s[M][N]; // LLR缓存 reg [N-1:0] llr_cache[N]; // 迭代计数器 reg [4:0] iter_cnt = 0; // 初始化 initial begin // 将校验矩阵H初始化为全0 H = 'h0; // 将信息节点和校验节点的值初始化为0 l = 'h0; s = 'h0; end // 译码过程 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin // 复信号 llr_cache <= 'h0; iter_cnt <= 0; l <= 'h0; s <= 'h0; end else begin // 读取接收到的数据 llr_cache <= rx_data; // 迭代计数器加1 iter_cnt <= iter_cnt + 1; // 计算校验节点的值 for (int i = 0; i < M; i++) begin for (int j = 0; j < N; j++) begin s[i][j] = llr_cache[j] - s[i][j]; for (int k = 0; k < N; k++) begin if (H[i][k] && k != j) begin s[i][j] += l[k]; end end end end // 更新信息节点的值 for (int i = 0; i < K; i++) begin l[i] = 0; for (int j = 0; j < M; j++) begin if (H[j][i]) begin l[i] += s[j][i]; end end end // 判断是否需要继续迭代 if (iter_cnt == ITER_NUM) begin // 译码结束,输出解码结果 tx_data = l > 0; end end end endmodule ``` 在上面的代码中,我们使用了参数化的方式定义了LDPC码的参数,包括码长、信息数、校验数、迭代次数等。译码过程分为两个步骤:计算校验节点的值和更新信息节点的值。在计算校验节点的值时,我们使用了Min-Sum算法,并且使用了LLR缓存来存储接收到的数据。在更新信息节点的值时,我们根据校验矩阵H和校验节点的值来更新信息节点的值。最后,我们在译码结束时输出解码结果。 需要注意的是,上面的代码只是一个简单的LDPC译码器的实现,还需要进行更多的优化和验证工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值