作业2:计数器数码管显示

来源:互联网 发布:Apache cxf wsdl 编辑:程序博客网 时间:2024/06/08 17:58

计数器FPGA电路实验作业

实验内容1

内容要求
内容1视频:计数器单数码管显示

人工RTL图

  • 顶层设计

    • 时间基准模块的OV产生以1s为周期的脉冲信号;
    • 带使能的多周期计数器进行循环计数,并以时间基准模块的OV作为使能端;
    • 4-7译码器用于译码使在数码管上显示对应字符。
    • bdf
  • 时间基准模块

    • 在CLK的上升沿,判断计数值CNTVAL是否小于计数循环最大值MAX_VAL,若是,则输出CNTVAL+1,否则输出循环初值0。
    • 当计数到最大值时,OV溢出为1,代表一个周期。
    • cnt_sync
  • 带使能的多周期计数器

    •  同步高电平复位,在CLK上升沿,且RST高电平复位,给输出CNT、循环最大值CNT_VAL分别赋初值0、6。
    • RST低电平且使能有效时,判断输出CNT是否小于循环最大值CNT_VAL,若是,则输出CNT+1,否则输出CNT为0,并判断循环最大值CNT_VAL是否小于9,若是,则CNT_VAL++,否则CNT_VAL赋6。
    • 使能为0时,保持输出值CNT。
    • cnt_en_circle
  • 数码管4-8译码器_无小数点

    • 数码管为共阳极,即输出为低电压时,相应字码段点亮,反之熄灭。根据下图可得到译码字段即可,RTL根据译码字段通过或门可以画出来,略过。
    • 数码管

Quartus生成的RTL图

  • 顶层设计
    顶层设计
  • 时间基准模块
    时间基准
  • 带使能的多周期计数器
    带使能的多周期
  • 数码管4-8译码器_无小数点
    数码管

SignalTap分析

  • 计数器的计数值的SignalTap截图,使用Segment 模式,捕获一个完整的计数循环过程中所有的计数值。
  • 以时间基准模块的OV为触发信号,2k的采样深度,设置segmented为64段32点进行采样,结果如下:
    signaltap

代码片

  • 时间基准模块
module cnt_sync(  CLK   ,   // clock  CNTVAL,   // counter value  OV    );  // overflowparameter CNTVAL_WL = 32;parameter MAX_VAL = 50_000_000;//周期:50_000_000*0.02us=1sinput CLK;output [CNTVAL_WL-1:0] CNTVAL;output OV;reg [CNTVAL_WL-1:0] CNTVAL;reg OV;always @ (posedge CLK) begin  if(CNTVAL < MAX_VAL)    CNTVAL <= CNTVAL + 1'b1;  else    CNTVAL <= 0;endalways @ (CNTVAL) begin     //计数到最大值时,OV溢出  if(CNTVAL == MAX_VAL)    OV = 1'b1;  else    OV = 1'b0;endendmodule   // module cnt_sync
  • 带使能的多周期计数模块
module cnt_en_circle_0tomax6_9(  CLK   ,   // clock  EN    ,   //enable  RST   ,   //reset  CNT   ,   //output  OV    );input CLK , RST , EN ;output OV ;output [4-1:0] CNT;//output counter valueparameter CNT_VAL_MIN=6;    //counter cycle min valueparameter CNT_VAL_MAX=9;    //counter cycle max valuereg [4-1:0] CNT;reg [4-1:0] CNT_VAL=CNT_VAL_MIN;reg OV;//同步高电平复位always @ (posedge CLK) begin    if(RST)begin    //reset        CNT <= 0;        CNT_VAL <= CNT_VAL_MIN;    end    else begin        if(EN)begin //enable            if(CNT < CNT_VAL)                CNT <= CNT + 1'b1;            else begin                CNT <= 0;                if(CNT_VAL < CNT_VAL_MAX)   //判断计数值是否到达最大的循环值                    CNT_VAL <= CNT_VAL + 1'b1;                else                    CNT_VAL <= CNT_VAL_MIN;            end        end        else CNT <= CNT ;    endendalways @ (CNT)begin    if( CNT == CNT_VAL)        OV = 1'b1 ;    else        OV = 1'b0 ;endendmodule   // cnt_en_circle_0tomax6_
  • 数码管4-8译码器_无小数点
module dec_4to8(IN  ,OUT);input  [4-1:0] IN  ;output [8-1:0] OUT ;reg [8-1:0] OUT ;always @ (IN) begin  case(IN)  //判断输入值是几就相应编码使在数码管上显示对应字符    4'b0000: OUT = 8'b11000000;//0    4'b0001: OUT = 8'b11111001;//1    4'b0010: OUT = 8'b10100100;//2    4'b0011: OUT = 8'b10110000;//3    4'b0100: OUT = 8'b10011001;//4    4'b0101: OUT = 8'b10010010;//5    4'b0110: OUT = 8'b10000010;//6    4'b0111: OUT = 8'b11111000;//7    4'b1000: OUT = 8'b10000000;//8    4'b1001: OUT = 8'b10011000;//9    4'b1010: OUT = 8'b10001000;//A    4'b1011: OUT = 8'b10000011;//b    4'b1100: OUT = 8'b11000110;//C    4'b1101: OUT = 8'b10100001;//d    4'b1110: OUT = 8'b10000110;//E    4'b1111: OUT = 8'b10001110;//F    default: OUT = 8'bx;  endcaseendendmodule // module dec_4to8

实验内容2

实验要求
内容2视频:计数器四数码管显示

人工RTL图

  • 顶层设计

    • 时间基准模块的OV产生以1s为周期的脉冲信号;
    • 带使能的多周期计数器进行循环计数,并以时间基准模块的OV作为使能端;
    • to_dec模块用来将计数值选择在哪个数码管上显示;
    • 4-8译码器用于译码使在数码管上显示对应字符。
    • 顶层设计
  • 时间基准模块

    • 在CLK的上升沿,判断计数值CNTVAL是否小于计数循环最大值MAX_VAL,若是,则输出CNTVAL+1,否则输出循环初值0。
    • 当计数到最大值时,OV溢出为1,代表一个周期。
    • cnt_sync
  • 带使能的多周期计数器

    • 异步高电平复位,RST高电平时,给输出CNT、循环最大值CNT_VAL分别赋初值0、6。
    • RST低电平且使能有效时,判断输出CNT是否小于循环最大值CNT_VAL,若是,则输出CNT+1,否则输出CNT为0,并判断循环最大值CNT_VAL是否小于9,若是,则CNT_VAL++,否则CNT_VAL赋6。
    • 使能为0时,保持输出值CNT。
    • 带使能端的
  • to_dec模块

    • 16位的输出送给四个4-8译码管,来控制数码管亮灭和显示数字
    • 复位时,16位的输出全置1,则数码管就全灭掉
    • 在EN的下降沿,计EN的数。由case语句判断计数0,1,2,3,则相应的数码管就会显示数字。
  • 数码管4-8译码器_无小数点

    • 数码管为共阳极,即输出为低电压时,相应字码段点亮,反之熄灭。当四个数码管的所有字段都为高时,4个数码管都熄灭。

Quartus生成的RTL图

  • 顶层设计
    顶层设计
  • 时间基准模块
    cnt_sync
  • 带使能的多周期计数器
    带使能的多周期
  • to_dec模块
    to_dec

SignalTap分析

  • 计数器的计数值的SignalTap截图,使用Segment 模式,捕获一个完整的计数循环过程中所有的计数值。
  • 以时间基准模块的OV为触发信号,256点的采样深度,设置segmented为64段4点进行采样,结果如下:
    总采样结果
  • 在数码管上显示情况:左1-FFFx;左2-FFxF;左3-FxFF;右1-xFFF。其中x表示在数码管上显示的相应数字。以数码管左1和左2的显示情况为例,SignalTap见下图:
    数码管显示情况
  • 复位时所有数码管熄灭:
    复位时熄灭
  • 本设计仍存在的问题:复位之后,0显示的时间不足1s,这是由于采用上升沿触发、高电平复位。

代码片

  • 时间基准模块
module cnt_sync(  CLK   ,   // clock  CNTVAL,   // counter value  OV    );  // overflowparameter CNTVAL_WL = 32;parameter MAX_VAL = 50_000_000;//周期:50_000_000*0.02us=1sinput CLK;output [CNTVAL_WL-1:0] CNTVAL;output OV;reg [CNTVAL_WL-1:0] CNTVAL;reg OV;always @ (posedge CLK) begin  if(CNTVAL < MAX_VAL)    CNTVAL <= CNTVAL + 1'b1;  else    CNTVAL <= 0;endalways @ (CNTVAL) begin     //计数到最大值时,OV溢出  if(CNTVAL == MAX_VAL)    OV = 1'b1;  else    OV = 1'b0;endendmodule   // module cnt_sync
  • 带使能的多周期计数器
module cnt_en_circle_0tomax6_9(  CLK   ,   // clock  EN    ,  RST   ,   //asynchronous reset, active high  CNT   ,   // output  OV    );input CLK , RST , EN ;output OV ;output [4-1:0] CNT;//output counter valueparameter CNT_VAL_MIN=6;    //counter cycle min valueparameter CNT_VAL_MAX=9;    //counter cycle max valuereg [4-1:0] CNT;reg [4-1:0] CNT_VAL=CNT_VAL_MIN;reg OV;//异步高电平复位always @ (posedge CLK or posedge RST) begin    if(RST)begin        CNT <= 0;        CNT_VAL <= CNT_VAL_MIN;    end    else begin        if(EN)begin            if(CNT < CNT_VAL)                CNT <= CNT + 1'b1;            else begin                CNT <= 0;                if(CNT_VAL < CNT_VAL_MAX)                    CNT_VAL <= CNT_VAL + 1'b1;                else                    CNT_VAL <= CNT_VAL_MIN;            end        end        else CNT <= CNT ;    endendalways @ (CNT)begin    if( CNT == CNT_VAL)        OV = 1'b1 ;    else        OV = 1'b0 ;endendmodule   // cnt_en_circle_0tomax6_9
  • to_dec模块
module to_dec(//  CLK  ,//本模块不需要用到    IN   ,    EN   ,//enable counter    RST  ,//asynchronous reset, active high    OUT);input EN,RST;input [3:0]IN;output [3:0]OUT;reg [15:0]OUT;reg [3:0]CNT;always @ (negedge EN or posedge RST) begin//这里EN要采用下降沿,因为在EN高电平期间,对应的输入IN是最大值,这个值应算在前一个周期里,故用下降沿触发//如果采用上升沿触发,则EN高电平时的IN算在下一个周期,实际现象是:每个数码管的最大值圆周右移一位显示。    if(RST) begin        CNT <= 0;//      OUT[15:0]  <= 16'hffff;//注意:上面被注释掉的语句错误,否则编译出现错误如下//Error (10028): Can't resolve multiple constant drivers for net "OUT[15]" at rtl_module.v(60)//原因:OUT信号在两个always并行块里。两个进程里都有同一个条件判断的话,会产生并行信号冲突的问题。//同一个信号不允许在多个进程中赋值,否则则为多驱动。//进程的并行性决定了多进程不同能对同一个对象进行赋值。    end    else begin        if(CNT < 3)            CNT <= CNT + 1'b1;        else            CNT <= 0;    endendalways @ (CNT)begin    if(RST)        OUT[15:0]  <= 16'hffff; //all HEX LED turn off    else begin        case(CNT)            2'b00://the left-first HEX LED display                begin                    OUT[3:0]   <= IN[3:0];                    OUT[7:4]   <= 4'b1111;                    OUT[11:8]  <= 4'b1111;                    OUT[15:12] <= 4'b1111;                end            2'b01://the left-second HEX LED display                begin                    OUT[3:0]   <= 4'b1111;                    OUT[7:4]   <= IN[3:0];                    OUT[11:8]  <= 4'b1111;                    OUT[15:12] <= 4'b1111;                end            2'b10://the left-third HEX LED display                begin                    OUT[3:0]   <= 4'b1111;                    OUT[7:4]   <= 4'b1111;                    OUT[11:8]  <= IN[3:0];                    OUT[15:12] <= 4'b1111;                end            2'b11://the right-first HEX LED display                begin                    OUT[3:0]   <= 4'b1111;                    OUT[7:4]   <= 4'b1111;                    OUT[11:8]  <= 4'b1111;                    OUT[15:12] <= IN[3:0];                end        endcase     endendendmodule  //module to_dec
  • 数码管4-8译码器_无小数点
module dec_4to8(IN  ,OUT);input  [4-1:0] IN  ;output [8-1:0] OUT ;reg [8-1:0] OUT ;always @ (IN) begin  case(IN)  //判断输入值是几就相应编码使在数码管上显示对应字符    4'b0000: OUT = 8'b11000000;//0    4'b0001: OUT = 8'b11111001;//1    4'b0010: OUT = 8'b10100100;//2    4'b0011: OUT = 8'b10110000;//3    4'b0100: OUT = 8'b10011001;//4    4'b0101: OUT = 8'b10010010;//5    4'b0110: OUT = 8'b10000010;//6    4'b0111: OUT = 8'b11111000;//7    4'b1000: OUT = 8'b10000000;//8    4'b1001: OUT = 8'b10011000;//9    4'b1010: OUT = 8'b10001000;//A    4'b1011: OUT = 8'b10000011;//b    4'b1100: OUT = 8'b11000110;//C    4'b1101: OUT = 8'b10100001;//d    4'b1110: OUT = 8'b10000110;//E    4'b1111: OUT = 8'b11111111;//不显示    default: OUT = 8'bx;  endcaseendendmodule // module dec_4to8
0 0