基于EP4CE6F17C8的FPGA单数码管秒计数实例

一、电路模块

本例的电路模块与“基于EP4CE6F17C8的FPGA数码管动态显示实例”中的完全一样,此处就不再给出了。

二、实验代码

本例实现1个数码管循环显示字符1~F,显示间隔为1秒,代码使用Verilog编写,采用例化的形式,共有三个文件。

先编写数码管实现显示字形解码的程序,模块名称为seg_decode,文件名称为seg_decode.v,代码如下。

module seg_decode(
    input[3:0]  char_val,             //显示的字形,可显示0~F十六个字形,所以需要4位
    output reg[7:0] seg7              //字形编码,包含小数点,共8位
);

always@(*)                            //敏感信号为所有输入量
begin
    case(char_val)
        4'd0:seg7 <= 8'b1100_0000;    //字形0的编码
        4'd1:seg7 <= 8'b1111_1001;    //字形1的编码
        4'd2:seg7 <= 8'b1010_0100;    //字形2的编码
        4'd3:seg7 <= 8'b1011_0000;    //字形3的编码
        4'd4:seg7 <= 8'b1001_1001;    //字形4的编码
        4'd5:seg7 <= 8'b1001_0010;    //字形5的编码
        4'd6:seg7 <= 8'b1000_0010;    //字形6的编码
        4'd7:seg7 <= 8'b1111_1000;    //字形7的编码
        4'd8:seg7 <= 8'b1000_0000;    //字形8的编码
        4'd9:seg7 <= 8'b1001_0000;    //字形9的编码
        4'ha:seg7 <= 8'b1000_1000;    //字形A的编码
        4'hb:seg7 <= 8'b1000_0011;    //字形B的编码
        4'hc:seg7 <= 8'b1100_0110;    //字形C的编码
        4'hd:seg7 <= 8'b1010_0001;    //字形D的编码
        4'he:seg7 <= 8'b1000_0110;    //字形E的编码
        4'hf:seg7 <= 8'b1000_1110;    //字形F的编码
        default:seg7 <= 7'b111_1111;  //默认不显示
    endcase
end
endmodule

接下来编写秒计数程序,模块名称为count_m16,文件名称为count_m16.v,代码如下。

module count_m16(
      input          clk,                  //板载50HMz系统时钟
      input          rst,                  //复位按键
      input          en,                   //计数使能位 
      output reg[3:0]data                  //计数值,从0~F共16位,所以用4位
);

always@(posedge clk or negedge rst)       //敏感信号为时钟上沿或复位下沿
begin
    if(rst == 0)                          //低电平复位
        data <= 4'd0;                     //复位时计数值清零
    else if(en)                           //如果计数使能,则执行计数,否则保持上一次的值不变
    begin
        if(data == 4'd15)                 //如果计数到达F时,
            data <= 4'd0;                 //计数值清零
        else
            data <= data + 4'd1;           //否则计数值加1
    end
end
endmodule

最后编写数码管显示程序,并设置为顶层模块,模块名称为seg_count,文件名称为seg_count.v,代码如下。

module seg_count(
    input clk,                            //板载50HMz系统时钟
    input rst,                            //复位按键
    output [7:0] seg,                     //段码端口
    output bit                            //位选端口
);
assign bit = 1'b0;                        //点亮数码管
reg [25:0] cnt;                           //定义26位时钟计数器
reg sec;                                  //定义秒信号
always@(posedge clk or negedge rst)       //敏感信号为时钟上沿或复位下沿
begin
    if(rst == 0)                          //低电平复位时秒计数清零
    begin
        sec <= 1'b0;
        cnt <= 26'd0;
    end
    else if(cnt == 26'd49_999_999)        //时钟计数器到达1秒时
    begin
        cnt <= 26'd0;                     //时钟计数器清零
        sec <= 1'b1;                      //产生秒信号
    end
    else
    begin
        sec <= 1'b0;                      //否则秒信号清零
        cnt <= cnt + 26'd1;               //时钟计数器加1,即来一次时钟脉冲加一次
    end
end
wire [3:0] count_data;                    //定义显示的值
//下面例化1个秒计数单元
count_m16 U0(.clk(clk), .rst(rst), .en(sec), .data(count_data));
//下面例化1个字形解码单元
seg_decode S0(.char_val(count_data), .seg7(seg));
endmodule

三、代码说明

1、count_m16模块主要负责十六进制计数,在系统时钟的同步下,来一个en脉冲计一次数,计满后回零。计数的快慢取决于en端口输入的脉冲周期,产生的计数值则通过data端口向外输出。
2、seg_decode模块主要负责计数值到字形码的解码(转换),通过char_val端口向内输入计数值,转换成字形编码后通过seg7端口向外输出。
3、seg_count模块为顶层模块,负责产生秒时钟信号(即en脉冲),通过例化十六进制计数单元,把秒信号en传入,之后获得按秒变化的计数值count_data。同时通过例化数码管字形解码单元,把计数值count_data传入,之后获得字形编码seg7。最终获取的字形编码通过顶层的seg端口连接到数码管段码引脚,最低位数码管的位选引脚直接连接到低电平点亮。
4、元件例化是EDA设计中一种常用的手段,有点类似C语言中的函数调用,但它例化出来的是逻辑元器件。通过例化不仅能产生出实体元件,还能通过端口名关联的方式与外部进行连接,从而实现信号的输入和输出。

四、实验步骤

FPGA开发的详细步骤请参见“基于EP4CE6F17C8的FPGA开发流程(以半加器为例)”一文,本例只对不同之处进行说明。

本例工程放在D:\EDA_FPGA\Exam_4文件夹下,工程名称为Exam_4。有三个模块文件,一个名称为seg_count.v,设置为顶层实体,另外两个名称分别为seg_decode.v和count_m16.v,用于提供例化。其余步骤与“基于EP4CE6F17C8的FPGA开发流程”中的一样。

接下来看管脚约束,本例中只用到了最低位的1个数码管,一共有9个引脚,再加上时钟晶振和复位按钮,一共11个。具体的端口分配如下图所示。

对于未用到的引脚设置为三态输入方式,多用用途引脚全部做为普通I/O端口,电压设置为3.3-V LVTTL(与”基于EP4CE6F17C8的FPGA开发流程“中的一样)。需要注意,程序中的每个端口都必须为其分配管脚,如果系统中存在未分配的I/O,软件可能会进行随机分配,这将造成不可预料的后果,存在烧坏FPGA芯片的风险。

接下来对工程进行编译,编译完成后,可查看一下逻辑器件的消耗情况,如下图所示。

另外,还可以点击菜单Tools->Netlist Viewers->RTL Viewer,查看一下生成的RTL电路图,如下图所示。

最后进行程序下载,并查看结果。下面是数码管动态显示十六进制秒计数图片的其中几张。

…………

当按下复位键后,数码管熄灭,如下图所示。

posted @ 2024-03-21 21:39  fxzq  阅读(178)  评论(0编辑  收藏  举报