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

    xiaoxiao2021-12-14  20

    计数器FPGA电路实验作业

    实验内容1

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

    人工RTL图

    顶层设计

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

    时间基准模块

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

    带使能的多周期计数器

     同步高电平复位,在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。

    数码管4-8译码器_无小数点

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

    Quartus生成的RTL图

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

    SignalTap分析

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

    代码片

    时间基准模块 module cnt_sync( CLK , // clock CNTVAL, // counter value OV ); // overflow parameter CNTVAL_WL = 32; parameter MAX_VAL = 50_000_000;//周期:50_000_000*0.02us=1s input 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; end always @ (CNTVAL) begin //计数到最大值时,OV溢出 if(CNTVAL == MAX_VAL) OV = 1'b1; else OV = 1'b0; end endmodule // 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 value parameter CNT_VAL_MIN=6; //counter cycle min value parameter CNT_VAL_MAX=9; //counter cycle max value reg [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 ; end end always @ (CNT)begin if( CNT == CNT_VAL) OV = 1'b1 ; else OV = 1'b0 ; end endmodule // 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; endcase end endmodule // module dec_4to8

    实验内容2

    内容2视频:计数器四数码管显示

    人工RTL图

    顶层设计

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

    时间基准模块

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

    带使能的多周期计数器

    异步高电平复位,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图

    顶层设计 时间基准模块 带使能的多周期计数器 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 ); // overflow parameter CNTVAL_WL = 32; parameter MAX_VAL = 50_000_000;//周期:50_000_000*0.02us=1s input 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; end always @ (CNTVAL) begin //计数到最大值时,OV溢出 if(CNTVAL == MAX_VAL) OV = 1'b1; else OV = 1'b0; end endmodule // 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 value parameter CNT_VAL_MIN=6; //counter cycle min value parameter CNT_VAL_MAX=9; //counter cycle max value reg [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 ; end end always @ (CNT)begin if( CNT == CNT_VAL) OV = 1'b1 ; else OV = 1'b0 ; end endmodule // 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; end end always @ (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 end end endmodule //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; endcase end endmodule // module dec_4to8
    转载请注明原文地址: https://ju.6miu.com/read-970866.html

    最新回复(0)