我试图制作一个2位数的BCD计数器,计数从0到99.我面临的问题是,电路板上的7段表示同时都在改变数字。 scenairio就像这样 - 00,11,22 ...... 99。
这是主要的逻辑代码:
module PartD(
output reg[0:6] lcd, //for one particular 7 segment LCD.
input clock,
output reg[0:7] sel // for selecting which LCD to be used
);
integer count=0;
//integer i=0, j=0;
reg[3:0] i, j; //4 bit reg for counting
always@(posedge clock)
begin
if(count==100000000) //(100MHz) count till 100M cycles...(1 sec delay)
begin
count = 0;
sel=00000001; //selecting the most significant digit
case (i)
0: lcd = 7'b0000001;
1: lcd = 7'b1001111;
2: lcd = 7'b0010010;
3: lcd = 7'b0000110;
4: lcd = 7'b1001100;
5: lcd = 7'b0100100;
6: lcd = 7'b0100000;
7: lcd = 7'b0001111;
8: lcd = 7'b0000000;
9: lcd = 7'b0000100;
endcase
sel=00000010; //selecting the least significant digit
case (j)
0: lcd = 7'b0000001;
1: lcd = 7'b1001111;
2: lcd = 7'b0010010;
3: lcd = 7'b0000110;
4: lcd = 7'b1001100;
5: lcd = 7'b0100100;
6: lcd = 7'b0100000;
7: lcd = 7'b0001111;
8: lcd = 7'b0000000;
9: lcd = 7'b0000100;
endcase
j = j+1;
if(j>9)
begin
j=0;
i = i+1; //increment i only when j overflows.
if(i>9)
i = 0;
end
end
else count = count + 1;
end
endmodule
由于两个显示器都在同时更改,因此似乎存在一些逻辑错误。会是什么呢。我是否犯了不考虑硬件的错误?
答案 0 :(得分:3)
您的代码存在的主要问题是,当您的计数器为100000000时,您试图在同一周期内激活两个LCD段。逻辑上,您使用阻塞分配'=',第二个分配有效地覆盖第一个分配。
您需要决定何时开启每个细分。
根据您的要求,我会找到一种方法在50%的时间内驱动每个细分。假设10 ^ 8的最大2 ^ n除数是256,我选择使用count [7]来决定段1和段2之间,以便在移动到另一段之前刷新每个段128个周期。
此外,您遇到语法错误,忘记在sel分配上使用二进制前缀(0000010而不是'b000010)。
这是使其正常工作的最低要求。
在实践中,我会进一步改变这一点并将其分解为几个“总是”的块:
一个用于柜台
一个用于显示器
一个用于递增i和j。
我还选择将计数器从整数类型替换为寄存器类型。保留非硬件结构的整数(用于循环计数器等)
为case语句添加了一个默认值,将x驱动为'lcd'。这有助于优化意外的i,j值(10..15)的合成以及传播x以进行模拟。
我还添加了一个复位输入并移动了时钟&将信号复位为模块接口上的第一个信号。没有重置,你的计数,i,j从随机值开始。在你的情况下,他们最终会合法,但它会使模拟变得更难,因为它们以“x”值开头。
另外,请记住阻止('=')和非阻塞('< =')分配之间的区别。尝试避免像使用时钟一样阻止使用阻塞分配。
module PartD(
input clock,
input reset,
output reg[0:6] lcd, //for one particular 7 segment LCD.
output reg[0:7] sel // for selecting which LCD to be used
);
reg [26:0]count;
reg[3:0] i, j; //4 bit reg for counting
always@(posedge clock)
begin
count <= reset ? 'd0 : (count == 100000000) ? 'd0 : (count + 1);
end
always@(posedge clock)
begin
j <= reset ? 'b0 : (j < 9) ? j+1 : 'b0;
i <= reset ? 'b0 : (j < 9) ? i : (i < 9) ? (i + 1) : 'b0;
end
always@(posedge clock)
begin
if (count & 128)
begin
sel <= 'b00000001; //selecting the most significant digit
case (i)
0: lcd <= 7'b0000001;
1: lcd <= 7'b1001111;
2: lcd <= 7'b0010010;
3: lcd <= 7'b0000110;
4: lcd <= 7'b1001100;
5: lcd <= 7'b0100100;
6: lcd <= 7'b0100000;
7: lcd <= 7'b0001111;
8: lcd <= 7'b0000000;
9: lcd <= 7'b0000100;
default:
lcd <= 'bx;
endcase
end
else
begin
sel <= 'b00000010; //selecting the least significant digit
case (j)
0: lcd <= 7'b0000001;
1: lcd <= 7'b1001111;
2: lcd <= 7'b0010010;
3: lcd <= 7'b0000110;
4: lcd <= 7'b1001100;
5: lcd <= 7'b0100100;
6: lcd <= 7'b0100000;
7: lcd <= 7'b0001111;
8: lcd <= 7'b0000000;
9: lcd <= 7'b0000100;
default:
lcd <= 'bx;
endcase
end
end
endmodule
答案 1 :(得分:0)
我面临的问题是,板上的7段赔付都在同时改变数字
假设您选择的刷新周期为 1 ms 。这意味着每个数字在周期的1/8内保持活动状态(对于8位数显示)。换句话说,数字周期为1/8 ms。这个周期连续发生,从而呈现出独立且持续点亮的数字,这是产生2位数BCD计数器的目的之一。
我们可以将现有的FPGA时钟转换为一个计数器,该计数器的值递增到与1到16ms之间的刷新周期相对应的值。如果将内部时钟频率除以刷新频率,这将为我们提供整个刷新周期的计数器值。
接下来,我们必须决定如何触发正确的数字,同时使用数字句点从0到99进行计数。在下面的代码中,对于第一种情况,我们利用寄存器“ refresh_counter”的宽度
module PartD(
input MHZ,
output reg DP = 1'b1,
output reg [6:0] A_TO_G,
output reg [7:0] AN
);
localparam divisor = 50000000;
reg [25:0] counter = 0;
reg clock = 0;
always@(posedge MHZ) begin
if (counter < divisor) begin
counter <= counter + 1;
clock <= clock;
end
else begin
counter <= 0;
clock <= ~clock; end
end
reg [16:0] refresh_counter = 0; //17 bits wide
always@(posedge MHZ) begin
refresh_counter <= refresh_counter + 1;
end
reg [3:0] num_one, num_two;
always@(posedge clock) begin
if(num_one == 4'd9) begin
num_one <= 0;
if (num_two == 4'd9)
num_two <= 0;
else
num_two <= num_two + 1;
end
else
num_one <= num_one + 1;
end
reg [3:0] NUMBER;
always@(refresh_counter or num_one or num_two) begin
// digit_per = 0.5 ms ---> digit_freq = 2000 Hz
// mhz_freq = 100*10^6 Hz
// bit = log(mhz_freq/digit_freq)/log(2)
// bit_position = bit - 1
// refresh_counter[bit_position]
case(refresh_counter[15])
1'b0: begin
AN = 8'b11111110;
NUMBER = num_one;
end
1'b1: begin
AN = 8'b11111101;
NUMBER = num_two;
end
endcase
end
always@(NUMBER) begin
case(NUMBER)
0: A_TO_G = 7'b0000001;
1: A_TO_G = 7'b1001111;
2: A_TO_G = 7'b0010010;
3: A_TO_G = 7'b0000110;
4: A_TO_G = 7'b1001100;
5: A_TO_G = 7'b0100100;
6: A_TO_G = 7'b0100000;
7: A_TO_G = 7'b0001111;
8: A_TO_G = 7'b0000000;
9: A_TO_G = 7'b0000100;
default: A_TO_G = 7'b0000001;
endcase
end
endmodule