集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
楼主: lcytms

FPGA初级课程第十二讲 二进制转BCD

[复制链接]
 楼主| lcytms 发表于 2016-11-14 17:05:11 | 显示全部楼层
加上数据控制模块data_controller和数码管模块seg7后,架构图如下。
其中,数据控制模块data_controller循环输出0~999999(对应十六进制的0~F423F),b2bcd模块将其转化为BCD数据000000~999999,提交给数码管模块seg7进行显示。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-14 17:07:11 | 显示全部楼层
建模主体框架

首先建立工程文件夹b2bcd,编写顶层模块b2bcd.v文件。

module b2bcd (din, dout);

        input [19:0] din;
       
        output [23:0] dout;
       
        wire [43:0] data [20:0];
       
        assign data[0] = {24'b0, din};                //第一步:准备阶段。将输入二进制数在高位补齐全0的BCD位,生成二进制全序列的初始状态。

       
        shift s01 (.datain(data[0]), .dataout(data[1]));                //第二步:移位阶段。依次进行20个小步操作。具体动作在shift子模块中描述。
        shift s02 (.datain(data[1]), .dataout(data[2]));
        shift s03 (.datain(data[2]), .dataout(data[3]));
        shift s04 (.datain(data[3]), .dataout(data[4]));
        shift s05 (.datain(data[4]), .dataout(data[5]));
        shift s06 (.datain(data[5]), .dataout(data[6]));
        shift s07 (.datain(data[6]), .dataout(data[7]));
        shift s08 (.datain(data[7]), .dataout(data[8]));
        shift s09 (.datain(data[8]), .dataout(data[9]));
        shift s10 (.datain(data[9]), .dataout(data[10]));
        shift s11 (.datain(data[10]), .dataout(data[11]));
        shift s12 (.datain(data[11]), .dataout(data[12]));
        shift s13 (.datain(data[12]), .dataout(data[13]));
        shift s14 (.datain(data[13]), .dataout(data[14]));
        shift s15 (.datain(data[14]), .dataout(data[15]));
        shift s16 (.datain(data[15]), .dataout(data[16]));
        shift s17 (.datain(data[16]), .dataout(data[17]));
        shift s18 (.datain(data[17]), .dataout(data[18]));
        shift s19 (.datain(data[18]), .dataout(data[19]));
        shift s20 (.datain(data[19]), .dataout(data[20]));

        assign dout = data[20][43:20];                //第三步:输出阶段。取出BCD部分,作为输出。

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-14 17:08:21 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-14 22:13 编辑

建模shift移位子模块

shift移位子模块shift.v文件如下:

module shift (datain, dataout);

        input [43:0] datain;
       
        output [43:0] dataout;
       
        wire [43:0] data;
       
        assign data[19:0] = datain[19:0];
       
        pre_shift p0 (.d4in(datain[23:20]), .d4out(data[23:20]));                //对应第二步各小步下的a操作,此处为6个BCD位的大四加三操作。具体动作见pre_shift移位预操作子模块。
        pre_shift p1 (.d4in(datain[27:24]), .d4out(data[27:24]));
        pre_shift p2 (.d4in(datain[31:28]), .d4out(data[31:28]));
        pre_shift p3 (.d4in(datain[35:32]), .d4out(data[35:32]));
        pre_shift p4 (.d4in(datain[39:36]), .d4out(data[39:36]));
        pre_shift p5 (.d4in(datain[43:40]), .d4out(data[43:40]));
       
        assign dataout = {data[42:0], 1'b0};                //对应第二步各小步下的b操作,此处为全序列的左移移位操作。

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-14 22:23:06 | 显示全部楼层
建模pre_shift预移位操作子模块

pre_shift预移位操作子模块pre_shift.v文件如下:

module pre_shift (d4in, d4out);

        input [3:0] d4in;
       
        output reg [3:0] d4out;
       
        always @ (*)
                begin
                        if (d4in > 4)
                                begin
                                        d4out = d4in + 3;                //如果大于四,则加三
                                end
                        else
                                begin
                                        d4out = d4in;                //如果不大于四,则不变
                                end
                end

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-14 22:29:30 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-14 22:30 编辑

pre_shift预移位操作子模块,也可以这样写

module pre_shift (d4in, d4out);

        input [3:0] d4in;
        
        output [3:0] d4out;
        
        assign d4out = (d4in > 4) ? d4in + 4'd3 : d4in;         //如果大于四,则加三,否则不变。

//        always @ (*)
//                begin
//                        if (d4in > 4)
//                                begin
//                                        d4out = d4in + 3;
//                                end
//                        else
//                                begin
//                                        d4out = d4in;
//                                end
//                end

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-14 22:32:05 | 显示全部楼层
编写Testbench模块


Testbench模块b2bcd_tb.v文件如下:

`timescale 1ns/1ps

module b2bcd_tb;

        reg [19:0] din;
       
        wire [23:0] dout;
       
        integer i;
       
        b2bcd dut (.din(din), .dout(dout));
       
        initial
                begin
                        din = 0;
                        for (i=0; i<=999999; i=i+1) #10 din = i;                //六位数码管循环显示000000~999999
                       
                        #100 $stop;
                end

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-14 22:33:06 | 显示全部楼层
仿真运行结果


设置好仿真之后,可以看到仿真结果。
此时将din的数据格式设置为无符号数Unsigned,将dout的数据格式设置为十六进制数Hexadecimal。
可以看到两种不同码制的数据保持了完全一致。
从一个方面验证了大四加三算法的正确性。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-14 22:36:12 | 显示全部楼层
用generate for语句改写shift移位子模块shift.v文件

我们注意到由于存在重复性操作,相同的语句往往写好多次。当然参数会稍微有所差异。
有个偷懒的办法,就是采用generate for语句。
用generate for语句改写的shift移位子模块shift.v文件如下所示:

module shift (datain, dataout);

        input [43:0] datain;
       
        output [43:0] dataout;
       
        wire [43:0] data;
       
        assign data[19:0] = datain[19:0];
       
//        pre_shift p0 (.d4in(datain[23:20]), .d4out(data[23:20]));
//        pre_shift p1 (.d4in(datain[27:24]), .d4out(data[27:24]));
//        pre_shift p2 (.d4in(datain[31:28]), .d4out(data[31:28]));
//        pre_shift p3 (.d4in(datain[35:32]), .d4out(data[35:32]));
//        pre_shift p4 (.d4in(datain[39:36]), .d4out(data[39:36]));
//        pre_shift p5 (.d4in(datain[43:40]), .d4out(data[43:40]));
       
        genvar i;
       
        generate for (i=0; i<24; i=i+4)
                begin        :        g4i
                        pre_shift p (.d4in(datain[23+i:20+i]), .d4out(data[23+i:20+i]));        //对应第二步各小步下的a操作,此处为6个BCD位的大四加三操作。具体动作见preshift移位预操作子模块。
                end
        endgenerate
       
        assign dataout = {data[42:0], 1'b0};                //对应第二步各小步下的b操作,此处为全序列的左移移位操作。

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-14 22:37:13 | 显示全部楼层
用generate for语句改写顶层模块b2bcd.v文件

同样的道理,我们对顶层模块b2bcd.v文件的重复性语句也进行了改写。
用generate for语句改写的顶层模块b2bcd.v文件如下所示:

module b2bcd (din, dout);

        input [19:0] din;
       
        output [23:0] dout;
       
        wire [43:0] data [20:0];
       
        assign data[0] = {24'b0, din};                //第一步:准备阶段。将输入二进制数在高位补齐全0的BCD位,生成二进制全序列的初始状态。
       
        genvar i;
       
        generate for (i=0; i<20; i=i+1)
                begin        :        g4i
                        shift s (.datain(data), .dataout(data[i+1]));                //第二步:移位阶段。依次进行20个小步操作。具体动作在shift子模块中描述。
                end
        endgenerate

        assign dout = data[20][43:20];                //第三步:输出阶段。取出BCD部分,作为输出。

endmodule
 楼主| lcytms 发表于 2016-11-14 22:38:53 | 显示全部楼层
第二步的小步次数优化

前面表格中我们提到,第二步的最初3小步可以去除,因为最初3小步除了左移操作,在BCD位大四加三操作中并不发生变化。
因此可以在第一步直接将原初始状态左移三位,原第二步直接跳过前3小步执行即可。
优化结果体现在顶层模块b2bcd.v文件中,如下所示:

module b2bcd (din, dout);

        input [19:0] din;
       
        output [23:0] dout;
       
        wire [43:0] data [20:0];
       
//        assign data[0] = {24'b0, din};
        assign data[3] = {21'b0, din, 3'b0};                 //第一步:准备阶段。将输入二进制数在高位补齐全0的BCD位,直接左移三位,生成二进制全序列的初始状态。
       
        genvar i;
       
//        generate for (i=0; i<20; i=i+1)
        generate for (i=3; i<20; i=i+1)
                begin        :        g4i
                        shift s (.datain(data), .dataout(data[i+1]));                //第二步:移位阶段。依次进行17个(20-3)小步操作。具体动作在shift子模块中描述。
                end
        endgenerate

        assign dout = data[20][43:20];                  //第三步:输出阶段。取出BCD部分,作为输出。

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-12-24 00:22 , Processed in 0.069915 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表