Zedboard—实验七秒表
在上节实验中的计数器是一个16进制的计数器,只能从0计到15。这节做类似秒表的计数器从0计到59。
硬件实现十进制计数
如果用软件来实现这个任务是很简单的:只需相除和取余运算就可以得到十进制数。实际上这些运算器相对实现起来成本较高。使用硬件实现,完成十进制计数。首先,创建一个模块代表十进制数。输出BCD(Bingary Coded Decimal)。代码:
`timescale 1ns/1ns
module bcd_digit
#(
parameter modulus = 10
)
(
input clk,
input carry_in,
output reg [$clog2(modulus)-1:0] digit,
output carry_out
);
initial digit = 0;
assign carry_out = carry_in && digit == modulus-1;
always @(posedge clk)
if (carry_in)
if (carry_out)
digit <= 0;
else
digit <= digit+1;
endmodule
参数modulus代表计数的最大值,carry_in为计数输入。carry_out可以作为进位信号输出。由于这里使用的是参数modulus,不能确定输出的位宽。所以使用内嵌函数$clog2以2为底取对数,来确定信号位宽。
由此修改上节实验中的top文件:
wire [7:0] sec_count;
wire ones_carry_out;
bcd_digit #(10) ones_digit
(
.clk(clk),
.carry_in(sec_pulse),
.digit(sec_count[3:0]),
.carry_out(ones_carry_out)
);
bcd_digit #(6) tens_digit
(
.clk(clk),
.carry_in(ones_carry_out),
.digit(sec_count[6:4]),
.carry_out()
);
assign sec_count[7] = 0;
由于计数最大值为59,即十位最大值为5。所以这里只用了3为来代表十位数值sec_count[6:4]。
修改测试文件
由于测试模块是软件实现,所以使用了整除和取余操作。
`timescale 1ns/1ns
module model
#(
parameter ms_limit = 100000
)
(
input clk,
output [7:0] seconds
);
integer counter = 0;
always @(posedge clk)
counter <= counter+1;
reg [7:0] seconds_value;
always @(posedge clk)
seconds_value <= (counter / (ms_limit * 1000))%60;
assign seconds[3:0] = seconds_value % 10;
assign seconds[7:4] = seconds_value / 10;
endmodule
原文连接