集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
楼主: lcytms

把二进制变成BCD码需要几步?——漫谈大四加三算法的Verilog实现

[复制链接]
 楼主| lcytms 发表于 2016-10-21 10:31:55 | 显示全部楼层
本帖最后由 lcytms 于 2016-10-21 10:33 编辑

仿真运行结果


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

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-10-21 10:43:46 | 显示全部楼层
本帖最后由 lcytms 于 2016-10-21 10:48 编辑

用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];
       
//        preshift p0 (.d4in(datain[23:20]), .d4out(data[23:20]));
//        preshift p1 (.d4in(datain[27:24]), .d4out(data[27:24]));
//        preshift p2 (.d4in(datain[31:28]), .d4out(data[31:28]));
//        preshift p3 (.d4in(datain[35:32]), .d4out(data[35:32]));
//        preshift p4 (.d4in(datain[39:36]), .d4out(data[39:36]));
//        preshift p5 (.d4in(datain[43:40]), .d4out(data[43:40]));
       
        genvar i;
       
        generate for (i=0; i<24; i=i+4)
                begin        :        g4i
                        preshift 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-10-21 10:53:32 | 显示全部楼层
本帖最后由 lcytms 于 2016-11-14 11:08 编辑

用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-10-21 11:10:15 | 显示全部楼层
本帖最后由 lcytms 于 2016-10-21 11:13 编辑

第二步的小步次数优化

前面表格中我们提到,第二步的最初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
 楼主| lcytms 发表于 2016-10-21 11:42:28 | 显示全部楼层
查看RTL视图——顶层模块b2bcd.v


顶层模块b2bcd.v的视图如下所示。
其中最下面为全局视图,上面为左边、右边的局部视图,可以看到17个子步shift移位模块逐次递进的一个结果。

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-10-21 11:46:25 | 显示全部楼层
本帖最后由 lcytms 于 2016-10-21 11:49 编辑

查看RTL视图——shift移位子模块shift.v

shift移位子模块shift.v的RTL视图如下。

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-10-21 11:49:28 | 显示全部楼层
查看RTL视图——preshift移位预操作子模块preshift.v


preshift移位预操作子模块preshift.v的RTL视图如下。

本帖子中包含更多资源

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

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

加入数码管驱动模块seg7.v文件

为了更直观地看到数码管显示效果,在已经做好的工程文件中加入编写好的数码管驱动模块seg7.v文件。
数码管驱动模块seg7.v文件如下所示。

module seg7 (clk, rst_n, data, sel, seg);

        input clk, rst_n;
        input [23:0] data;
       
        output reg [2:0] sel;
        output reg [7:0] seg;
       
       
        reg [19:0] count;
        reg clk_1ms;
       
        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        clk_1ms <= 1;
                                end
                        else
                                begin
                                        if (count < 24999)
                                                begin
                                                        count <= count + 20'd1;
                                                end
                                        else
                                                begin
                                                        count <= 0;
                                                        clk_1ms <= ~clk_1ms;
                                                end
                                end
                end

               
        reg [2:0] state;
        reg [3:0] data_temp;

        always @ (posedge clk_1ms or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        sel <= 0;
                                        data_temp <= 0;
                                        state <= 0;
                                end
                        else
                                begin
                                        case (state)
                                        0        :        begin
                                                                sel <= 0;
                                                                data_temp <= data[23:20];
                                                                state <= 1;
                                                        end
                                       
                                        1        :        begin
                                                                sel <= 1;
                                                                data_temp <= data[19:16];
                                                                state <= 2;
                                                        end
                                       
                                        2        :        begin
                                                                sel <= 2;
                                                                data_temp <= data[15:12];
                                                                state <= 3;
                                                        end
                                       
                                        3        :        begin
                                                                sel <= 3;
                                                                data_temp <= data[11:8];
                                                                state <= 4;
                                                        end
                                       
                                        4        :        begin
                                                                sel <= 4;
                                                                data_temp <= data[7:4];
                                                                state <= 5;
                                                        end
                                       
                                        5        :        begin
                                                                sel <= 5;
                                                                data_temp <= data[3:0];
                                                                state <= 0;
                                                        end
                                       
                                        default        :        state <= 0;
                                       
                                        endcase
                                end
                end
       
       
        always @ (*)
                begin
                        if (!rst_n)
                                begin
                                        seg = 8'b1111_1111;
                                end
                        else
                                begin
                                        case (data_temp)
                                        0        :        seg = 8'b1100_0000;                //d0
                                        1        :        seg = 8'b1111_1001;                //d1
                                        2        :        seg = 8'b1010_0100;                //d2
                                        3        :        seg = 8'b1011_0000;                //d3
                                        4        :        seg = 8'b1001_1001;                //d4
                                        5        :        seg = 8'b1001_0010;                //d5
                                        6        :        seg = 8'b1000_0010;                //d6
                                        7        :        seg = 8'b1111_1000;                //d7
                                        8        :        seg = 8'b1000_0000;                //d8
                                        9        :        seg = 8'b1001_0000;                //d9
                                        10        :        seg = 8'b1000_1000;                //dA
                                        11        :        seg = 8'b1000_0011;                //db
                                        12        :        seg = 8'b1100_0110;                //dC
                                        13        :        seg = 8'b1010_0001;                //dd
                                        14        :        seg = 8'b1000_0110;                //dE
                                        15        :        seg = 8'b1000_1110;                //dF
                                        default        :        seg = 8'b1000_1110;                //dF
                                        endcase
                                end
                end

endmodule

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-10-21 14:48:25 | 显示全部楼层
本帖最后由 lcytms 于 2016-10-21 14:53 编辑

创建新的顶层模块top.v

创建新的顶层模块top.v,循环生成要显示的数字000000~999999,显示数字每100ms更新一次,通过b2bcd模块转换成BCD码,然后输出给数码管驱动模块。
新的顶层模块top.v文件如下所示。

module top (clk, rst_n, sel, seg);

        input clk, rst_n;

        output [2:0] sel;
        output [7:0] seg;
       
       
        reg [31:0] count;
        reg [19:0] din;

        wire [23:0] dout;
       
        parameter T100ms = 5_000_000;
       
        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        count <= 0;
                                        din <= 0;
                                end
                        else
                                begin
                                        if (count < T100ms - 1)                                //显示数字每100ms更新一次
                                                begin
                                                        count <= count + 1;
                                                end
                                        else
                                                begin
                                                        count <= 0;
                                                        if (din < 999999)                                //循环生成要显示的数字000000~999999
                                                                begin
                                                                        din <= din + 20'd1;
                                                                end
                                                        else
                                                                begin
                                                                        din <= 0;
                                                                end
                                                end
                                end
                end

        b2bcd b2bcd
                (
                        .din(din),
                        .dout(dout)
                );
       
        seg7 seg7
                (
                        .clk(clk),
                        .rst_n(rst_n),
                        .data(dout),
                        .sel(sel),
                        .seg(seg)
                );


endmodule

本帖子中包含更多资源

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

x
 楼主| lcytms 发表于 2016-10-21 15:02:12 | 显示全部楼层
参照.tcl文件设置好FPGA管脚


参照EP4CE10F17C8Nzx_1.tcl文件内容,对FPGA芯片管脚进行设置。

EP4CE10F17C8Nzx_1.tcl文件相关内容如下所示。FPGA芯片配置结果如图所示。

        #set_global_assignment -name FAMILY "Cyclone IV"
        #set_global_assignment -name DEVICE ep4ce10f17c8n

set_location_assignment PIN_E1    -to    clk        

# KEY 轻触按键
set_location_assignment PIN_L3    -to   key[0]         

# SEG7 x 8 七段数码管
set_location_assignment PIN_L6    -to   sel[2]
set_location_assignment PIN_N6    -to   sel[1]
set_location_assignment PIN_M7    -to   sel[0]
set_location_assignment PIN_T11   -to   seg[0]     
set_location_assignment PIN_T10   -to   seg[1]   
set_location_assignment PIN_T9    -to   seg[2]     
set_location_assignment PIN_T8    -to   seg[3]     
set_location_assignment PIN_T7    -to   seg[4]     
set_location_assignment PIN_T6    -to   seg[5]     
set_location_assignment PIN_T5    -to   seg[6]     
set_location_assignment PIN_T4    -to   seg[7]

本帖子中包含更多资源

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

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

本版积分规则

关闭

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

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

GMT+8, 2024-11-23 11:23 , Processed in 0.065073 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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