利用verilog将二进制码转换为十进制BCD码

首先给出二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例):

               1.将二进制码左移一位(或者乘2)

               2.找到左移后的码所对应的个,十,百位。

               3.判断在个位和百位的码是否大于5,如果是则该段码加3。

               4.继续重复以上三步直到移位8次后停止。

下面是一个例子 ,将 1111_1111 转换为 BCD码 ,如果8bit数据最终移位得到18bit 数据 ,那么个位,十位,百位分别对应12~9,16~13,18~17位。                        

              

代码如下:

`timescale      1ns/1ps
// *********************************************************************************
// Project Name :       
// Author       : Wkj
// Email        : 
// Blogs        : https://hellocode.blog.csdn.net/article/details/109755812
// File Name    : Bin_BCD.v
// Module Name  :
// Called By    :
// Abstract     :
//
// CopyRight(c) 
// All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date         By              Version                 Change Description
// -----------------------------------------------------------------------
// 2018/8/12    NingHeChuan       1.0                     Original
//  
// *********************************************************************************

module Bin_BCD
#(
    parameter       DATA_WIDTH  =   16,
    parameter       SHIFT_WIDTH =   5,
    parameter       SHIFT_DEPTH =   16
    
)
(
    input               clk,
    input               rst_n,
    input               tran_en,
    input       [DATA_WIDTH - 1:0]  data_in,
    output   reg        tran_done,
    output      [3:0]   thou_data,      //千位
    output        [3:0]    hund_data,      //百位
    output        [3:0]    tens_data,      //十位
    output        [3:0]    unit_data       //个位

);
//-------------------------------------------------------
localparam  IDLE    =   3'b001;
localparam   SHIFT   =   3'b010;
localparam   DONE    =   3'b100;

//-------------------------------------------------------
reg     [2:0]   pre_state;
reg     [2:0]   next_state;
//
reg     [SHIFT_DEPTH-1:0]   shift_cnt;
//
reg     [DATA_WIDTH:0]  data_reg;
reg     [3:0]   thou_reg;
reg        [3:0]    hund_reg;
reg        [3:0]    tens_reg;
reg        [3:0]    unit_reg; 
reg     [3:0]   thou_out;
reg        [3:0]    hund_out;
reg        [3:0]    tens_out;
reg        [3:0]    unit_out; 
wire    [3:0]   thou_tmp;
wire    [3:0]    hund_tmp;
wire    [3:0]    tens_tmp;
wire    [3:0]    unit_tmp;

//-------------------------------------------------------
//FSM step1
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        pre_state <= IDLE;
    end
    else begin
        pre_state <= next_state;
    end
end

//FSM step2
always  @(*)begin
    case(pre_state)
    IDLE:begin
        if(tran_en == 1'b1)
            next_state = SHIFT;
        else 
            next_state = IDLE;
    end
    SHIFT:begin
        if(shift_cnt == SHIFT_DEPTH + 1)
            next_state = DONE;
        else 
            next_state = SHIFT;
    end
    DONE:begin
        next_state = IDLE;
    end
    default:next_state = IDLE;
    endcase
end

//FSM step3
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        thou_reg <= 4'b0; 
        hund_reg <= 4'b0; 
        tens_reg <= 4'b0; 
        unit_reg <= 4'b0; 
        tran_done <= 1'b0;
        shift_cnt <= 'd0; 
        data_reg <= 'd0;
    end
    else begin
        case(next_state)
        IDLE:begin
            thou_reg <= 4'b0; 
            hund_reg <= 4'b0; 
            tens_reg <= 4'b0; 
            unit_reg <= 4'b0; 
            tran_done <= 1'b0;
            shift_cnt <= 'd0; 
            data_reg <= data_in;
        end
        SHIFT:begin
            if(shift_cnt == SHIFT_DEPTH + 1)
                shift_cnt <= 'd0;
            else begin
                shift_cnt <= shift_cnt + 1'b1;
                data_reg <= data_reg << 1;
                unit_reg <= {unit_tmp[2:0], data_reg[16]};
                tens_reg <= {tens_tmp[2:0], unit_tmp[3]};
                hund_reg <= {hund_tmp[2:0], tens_tmp[3]};
                thou_reg <= {thou_tmp[2:0], hund_tmp[3]};
            end
        end
        DONE:begin
            tran_done <= 1'b1;
        end
        default:begin
            thou_reg <= thou_reg; 
            hund_reg <= hund_reg; 
            tens_reg <= tens_reg; 
            unit_reg <= unit_reg; 
            tran_done <= tran_done;
            shift_cnt <= shift_cnt; 
        end
        endcase
    end
end
//-------------------------------------------------------
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        thou_out <= 'd0;
        hund_out <= 'd0;
        tens_out <= 'd0;
        unit_out <= 'd0; 
    end
    else if(tran_done == 1'b1)begin
        thou_out <= thou_reg;
        hund_out <= hund_reg;
        tens_out <= tens_reg;
        unit_out <= unit_reg;
    end
    else begin
        thou_out <= thou_out;
        hund_out <= hund_out;
        tens_out <= tens_out;
        unit_out <= unit_out;
    end
end


//-------------------------------------------------------
assign  thou_tmp = (thou_reg > 4'd4)?  (thou_reg + 2'd3) : thou_reg;
assign  hund_tmp = (hund_reg > 4'd4)?  (hund_reg + 2'd3) : hund_reg;
assign  tens_tmp = (tens_reg > 4'd4)?  (tens_reg + 2'd3) : tens_reg; 
assign  unit_tmp = (unit_reg > 4'd4)?  (unit_reg + 2'd3) : unit_reg; 

assign thou_data = thou_out;
assign hund_data = hund_out;
assign tens_data = tens_out;
assign unit_data = unit_out;


endmodule 

1.本文部分素材来源网络,版权归原作者所有,如涉及作品版权问题,请与我联系删除。

2.未经原作者允许不得转载本文内容,否则将视为侵权;

3.转载或者引用本文内容请注明来源及原作者;

4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。

下面是我的个人微信公众号,关注【一个早起的程序员】精彩系列文章每天不断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个早起的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值