verliog-----六位十进制转6个8421BCD码

方案一,使用求余法

       思路一  使用assign

module bcd_8421_999999(
    input   wire           sys_clk             ,
    input   wire           sys_rst_n           ,
    input   wire    [19:0]  data                ,    //十进制  
    
    output  wire     [3:0]  ones_place          ,    //个位//对应的bcd_8421码
    output  wire     [3:0]  tens_place          ,    //十位
    output  wire     [3:0]  huns_place          ,    //百位
    output  wire     [3:0]  thos_place          ,    //千位
    output  wire     [3:0]  ten_thos_place      ,    //万位
    output  wire     [3:0]  hun_thos_place           //十万位  
    
);

    //方案一 
    
    assign ones_place = data % 10;
    assign tens_place = (data /10 ) %10;
    assign huns_place = (data /100 ) %10;
    assign thos_place = (data /1000 ) %10;
    assign ten_thos_place = (data /10000 ) %10;     
    assign  hun_thos_place = data / 100_000;


endmodule

tb代码

`timescale 1ns/1ns 

module tb_bcd_8421_999999();
    reg            sys_clk        ;
    reg            sys_rst_n      ;
    reg     [19:0]  data          ;
                                  
    wire    [3:0]  ones_place     ;
    wire    [3:0]  tens_place     ;
    wire    [3:0]  huns_place     ;
    wire    [3:0]  thos_place     ;
    wire    [3:0]  ten_thos_place ;
    wire    [3:0]  hun_thos_place ;
    
    initial begin
        sys_clk    = 1'b1;
        sys_rst_n <= 1'b0;
        data      <= 20'd987_654;
        #20
        sys_rst_n <= 1'b1;
        
        #200
        data       <= 20'd123_496;
        #200
        data       <= 20'd008_013;
        #500 $stop;
    end
    
    always #10 sys_clk = ~sys_clk;
    
    bcd_8421_999999 u_bcd_8421_999999(
        .sys_clk         (sys_clk         ),
        .sys_rst_n       (sys_rst_n       ),
        .data            (data            ),
        
        .ones_place      (ones_place      ),
        .tens_place      (tens_place      ),
        .huns_place      (huns_place      ),
        .thos_place      (thos_place      ),
        .ten_thos_place  (ten_thos_place  ),
        .hun_thos_place  (hun_thos_place  )    
    );
    



endmodule

仿真

资源使用量

思路二:将8个时钟为一组,第0个时钟进行初始化等操作,第1-6个时钟进行运算操作,第7个时钟进行输出。将输入传入到该模块,最大需要16个时钟周期才能传出结果

RTL代码如下

/*
    将十进制最大为  19'd999_999  的data 转为由6个8421的bcd码进行输出
*/


module bcd_8421_999999(
    input   wire           sys_clk             ,
    input   wire           sys_rst_n           ,
    input   wire    [19:0]  data                ,    //十进制  
    
    output  reg     [3:0]  ones_place          ,    //个位//对应的bcd_8421码
    output  reg     [3:0]  tens_place          ,    //十位
    output  reg     [3:0]  huns_place          ,    //百位
    output  reg     [3:0]  thos_place          ,    //千位
    output  reg     [3:0]  ten_thos_place      ,    //万位
    output  reg     [3:0]  hun_thos_place           //十万位  
    
);
    
//方案一--取模运算-----不建议-耗费资源比较多
     //六个时钟周期后输出
     reg    [2:0]   cnt     ;
     parameter      CNT_MAX = 3'd7;//0阶段为初始化阶段,1-6为运算阶段,7为输出阶段
     reg            flag_cnt;
     
     reg    [19:0]  data_temp;
     reg     [3:0]  temp_ones_place     ;
     reg     [3:0]  temp_tens_place     ;
     reg     [3:0]  temp_huns_place     ;
     reg     [3:0]  temp_thos_place     ;
     reg     [3:0]  temp_ten_thos_place ;
     reg     [3:0]  temp_hun_thos_place ;
     
     
     //计数
     always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            cnt <= 3'd0;
        else if(cnt == CNT_MAX)
            cnt <= 3'd0;
        else
            cnt <= cnt + 1'b1;
     end 
    //计数_flag
     always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)//复位时
            flag_cnt <= 1'b0;
        else if(cnt == (CNT_MAX -1))
            flag_cnt <= 1'b1;
        else
            flag_cnt <= 1'b0;
     end 

     always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)begin
            ones_place          <= 4'b0000;
            tens_place          <= 4'b0000;
            huns_place          <= 4'b0000;
            thos_place          <= 4'b0000;
            ten_thos_place      <= 4'b0000;
            hun_thos_place      <= 4'b0000;            
            temp_ones_place     <= 4'b0000;
            temp_tens_place     <= 4'b0000;
            temp_huns_place     <= 4'b0000;
            temp_thos_place     <= 4'b0000;
            temp_ten_thos_place <= 4'b0000;
            temp_hun_thos_place <= 4'b0000;
            data_temp           <= data;
        end
        else if(flag_cnt == 1'b0)begin
            case(cnt)
                4'd0    :   begin 
                                temp_ones_place     <= 4'b0000;
                                temp_tens_place     <= 4'b0000;
                                temp_huns_place     <= 4'b0000;
                                temp_thos_place     <= 4'b0000;
                                temp_ten_thos_place <= 4'b0000;
                                temp_hun_thos_place <= 4'b0000;
                                data_temp           <= data;
                            end
                4'd1    :   begin
                                temp_ones_place <= data_temp % 10;
                                data_temp  <= data_temp / 10;
                            end
                4'd2    :   begin
                                temp_tens_place <= data_temp % 10;
                                data_temp  <= data_temp / 10;
                            end                
                4'd3    :   begin
                                temp_huns_place <= data_temp % 10;
                                data_temp  <= data_temp / 10;
                            end 
                4'd4    :   begin
                                temp_thos_place <= data_temp % 10;
                                data_temp  <= data_temp / 10;
                            end 
                4'd5    :   begin
                                temp_ten_thos_place <= data_temp % 10;
                                data_temp  <= data_temp / 10;
                            end                 
                4'd6    :   begin
                                temp_hun_thos_place <= data_temp % 10;
                                data_temp  <= data_temp / 10;
                            end
         //取不到4'd7    :  cnt== 4'd7 flag_cnt == 1'b1; 
                default : ;
            endcase
        end
        else begin
            ones_place          <= temp_ones_place    ;
            tens_place          <= temp_tens_place    ;
            huns_place          <= temp_huns_place    ;
            thos_place          <= temp_thos_place    ;
            ten_thos_place      <= temp_ten_thos_place;
            hun_thos_place      <= temp_hun_thos_place;
        end
        
     end 
    
    
 

endmodule

下面是仿真结果

所使用资源

 方案二 使用<<法,推荐

思路:创建一个二分频的时钟周期,为移位判断信号,低电平时(一个时钟周期)进行判断,高电平时(一个时钟周期)进行移位

十进制最大为999_999的data,位宽为20,需要移动20次 ,根据上面创建的二分频时钟进行计数,最大为21。 0为初始化,1-20为判断和位移阶段,21为输出阶段

将输入传入到该模块,最大需要44个时钟周期才能传出结果

参考十进制转8421_BCD码_8421bcd码-CSDN博客

这是我写的RTL代码

module bcd_8421_999999(
    input   wire           sys_clk             ,
    input   wire           sys_rst_n           ,
    input   wire    [19:0]  data                ,    //十进制  
    
    output  reg     [3:0]  ones_place          ,    //个位//对应的bcd_8421码
    output  reg     [3:0]  tens_place          ,    //十位
    output  reg     [3:0]  huns_place          ,    //百位
    output  reg     [3:0]  thos_place          ,    //千位
    output  reg     [3:0]  ten_thos_place      ,    //万位
    output  reg     [3:0]  hun_thos_place           //十万位  
    
);
 //方案二 使用<<法,推荐
    reg            flag_shift       ;//移位判断信号,低电平判断,高电平移位,共计两个周期,第一个周期为底电平,第二个周期为高电平
    reg    [4:0]   cnt              ;//data 数据位宽20位,需要移动20次
    parameter      CNT_MAX = 5'd21  ;//0阶段为初始化阶段,1-20为运算阶段,21为输出阶段
    
    reg     [43:0] data_shift       ;//六个BCD吗加上data,共计24+20=44位宽
 
    //移位判断信号,低电平判断,高电平移位,共计两个周期,第一个周期为底电平,第二个周期为高电平
    always@(posedge sys_clk or negedge sys_rst_n)begin
        if(!sys_rst_n)
            flag_shift <= 1'b0;
        else
            flag_shift <= ~flag_shift;
    end
 
    //计数
     always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            cnt <= 5'd0;
        else if((cnt == CNT_MAX) && (flag_shift == 1'b1))
            cnt <= 5'd0;
        else if(flag_shift == 1'b1)
            cnt <= cnt + 1'b1;
        else
            cnt <= cnt;
     end 
     
     always@(posedge sys_clk or negedge sys_rst_n)begin
        if(!sys_rst_n)
            data_shift <= 44'd0;
        else if(cnt == 5'd0)
            data_shift <= {24'b0,data};//计数器为0时,初始化阶段
        else if((cnt <= 5'd20) && flag_shift == 1'b0)begin
            data_shift[23:20] <=  (data_shift[23:20]) > 4 ?(data_shift[23:20] + 2'd3):(data_shift[23:20]);
            data_shift[27:24] <=  (data_shift[27:24]) > 4 ?(data_shift[27:24] + 2'd3):(data_shift[27:24]);
            data_shift[31:28] <=  (data_shift[31:28]) > 4 ?(data_shift[31:28] + 2'd3):(data_shift[31:28]);
            data_shift[35:32] <=  (data_shift[35:32]) > 4 ?(data_shift[35:32] + 2'd3):(data_shift[35:32]);
            data_shift[39:36] <=  (data_shift[39:36]) > 4 ?(data_shift[39:36] + 2'd3):(data_shift[39:36]);
            data_shift[43:40] <=  (data_shift[43:40]) > 4 ?(data_shift[43:40] + 2'd3):(data_shift[43:40]);
        end
        else if((cnt <= 5'd20) && flag_shift == 1'b1)
            data_shift <= data_shift << 1'b1;
        else
            data_shift <= data_shift;//cnt == 21 最后一个阶段 保持,输出
     end
    
    //输出
    always@(posedge sys_clk or negedge sys_rst_n)begin
        if(!sys_rst_n)begin
            ones_place          <= 4'b0000;
            tens_place          <= 4'b0000;
            huns_place          <= 4'b0000;
            thos_place          <= 4'b0000;
            ten_thos_place      <= 4'b0000;
            hun_thos_place      <= 4'b0000;
        end
        else if(cnt == 5'd21)begin
            ones_place          <= data_shift[23:20] ;
            tens_place          <= data_shift[27:24] ;
            huns_place          <= data_shift[31:28] ;
            thos_place          <= data_shift[35:32] ;
            ten_thos_place      <= data_shift[39:36] ;
            hun_thos_place      <= data_shift[43:40] ;
        end
        else begin
            ones_place          <= ones_place    ;
            tens_place          <= tens_place    ;
            huns_place          <= huns_place    ;
            thos_place          <= thos_place    ;
            ten_thos_place      <= ten_thos_place;
            hun_thos_place      <= hun_thos_place;
        end
    end
endmodule

仿真结果

所用资源

方案三,使用组合逻辑一个时钟周期完成转换,推荐

上图可知,需要两个操作,一个时移位,一个是判断加3

框图如下

模块一,输入四位编码,判断是否大于4,大于,加三在输出,否则直接输出

模块二 进行一次移位和判断

顶层模块

bcd_8421_adjust  代码

module bcd_8421_adjust (

    input   wire    [3:0]   bcd_in, 
    output  wire    [3:0]   bcd_out
);
	//判断
	assign bcd_out = (bcd_in > 4) ? bcd_in + 3 : bcd_in;

endmodule 

bcd_8421_move  代码

module bcd_8421_move(
    input   [19:0]  move_in     ,
    output  [19:0]  move_out
);
    //三个十进制bcd 码
    wire [3:0]  bcd_reg_1;
    wire [3:0]  bcd_reg_2;
    wire [3:0]  bcd_reg_3;
    
    wire [19:0] d_reg;
    
    //十进制百位
    bcd_8421_adjust bcd_8421_adjust_inst1(
        .bcd_in         (move_in[19:16]), 
        .bcd_out        (bcd_reg_1)
    );
    //十进制十位
    bcd_8421_adjust bcd_8421_adjust_inst2(
        .bcd_in         (move_in[15:12]), 
        .bcd_out        (bcd_reg_2)
    );
    //十进制个位
    bcd_8421_adjust bcd_8421_adjust_inst3(
        .bcd_in         (move_in[11:8]), 
        .bcd_out        (bcd_reg_3)
    );
    
    assign d_reg = {bcd_reg_1, bcd_reg_2, bcd_reg_3, move_in[7:0]};
    assign move_out = d_reg << 1;
    

endmodule

bcd_8421 代码

module bcd_8421(
    input   wire    [7:0]   in_binary   ,   //最大值为十进制8'b1111_1111 = 8'd255
    output  wire    [11:0]  out_bcd         //三位十进制需要三个4位的bcd 吗,共计12位
    
);
    /*
    可以定义为数组模式
    wire    [19:0]  data_reg    [8:0]; 
    则 data_reg_0 = data_reg[0];,以此类推......
    
    */
    wire    [19:0]  data_reg_0    ; 
    wire    [19:0]  data_reg_1    ;
    wire    [19:0]  data_reg_2    ;
    wire    [19:0]  data_reg_3    ;
    wire    [19:0]  data_reg_4    ;
    wire    [19:0]  data_reg_5    ;
    wire    [19:0]  data_reg_6    ;
    wire    [19:0]  data_reg_7    ;
    wire    [19:0]  data_reg_8    ;

    
    assign  data_reg_0 = {12'b0000_0000_0000,in_binary};//初始化
    //第一次移动和判断
    bcd_8421_move move1(
        .move_in     (data_reg_0),
        .move_out    (data_reg_1)
    );
    
    //第2次移动和判断
    bcd_8421_move move2(
        .move_in     (data_reg_1),
        .move_out    (data_reg_2)
    );
    
    //第3次移动和判断
    bcd_8421_move move3(
        .move_in     (data_reg_2),
        .move_out    (data_reg_3)
    );
    
    
    //第4次移动和判断
    bcd_8421_move move4(
        .move_in     (data_reg_3),
        .move_out    (data_reg_4)
    );
    
    //第5次移动和判断
    bcd_8421_move move5(
        .move_in     (data_reg_4),
        .move_out    (data_reg_5)
    );
    
    //第6次移动和判断
    bcd_8421_move move6(
        .move_in     (data_reg_5),
        .move_out    (data_reg_6)
    );
    
    //第7次移动和判断
    bcd_8421_move move7(
        .move_in     (data_reg_6),
        .move_out    (data_reg_7)
    );
    //第8次移动和判断
    bcd_8421_move move8(
        .move_in     (data_reg_7),
        .move_out    (data_reg_8)
    );
    
    //最后将结果输出
    assign out_bcd = data_reg_8[19:8];

endmodule

tb代码

`timescale 1ns/1ns 

module tb_bcd_8421();
    reg     [7:0]   in_binary   ;
    wire    [11:0]  out_bcd     ;

    initial begin
        in_binary = 8'd123;
        #20
        in_binary = 8'd234;
        #100
        in_binary = 8'd12;
        #100;

    end
    
    bcd_8421 bcd_8421_inst(
       .in_binary  (in_binary ),
       .out_bcd    (out_bcd   )

    );
    
    
    
    
endmodule

仿真截图

资源使用量

简单做个记录

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值