1、请用Verilog RTL描述如下图设计:以clk为基准,设计一个秒计数器,在指定的计数值产生中断,实时输出当前的秒数计数值。
- clk是时钟输入,频率为32.768KHz。
- rst_n是异步复位输入,低电平有效,复位整个系统,为高则整个系统开始工作,其上升沿已经同步于clk。
- start是启动信号,一个clk时钟周期的正脉冲,同步于clk。alarm[7:0]是配置信息,单位为秒,同步于clk。
- 工作模式:收到start后,秒计数器sec_cnt从零开始以秒为单位来记述,计数到alarm[7:0]指定的数值时,产生一个int pluse(时钟周期的正脉冲),秒数计数器回零并停止。
2、代码书写
module sec(
input wire clk,
input wire rst_n,
input wire start,
input wire [7:0] alarm,
output wire int_pluse,
output reg [31:0] sec_cnt
);
reg flag;
reg [14:0] cnt ;
reg sec_flag;
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 15'd0;
else if(flag)
cnt <= cnt + 1'b1;
else
cnt <= 15'd0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
sec_flag <= 1'b0;
else if(cnt == 15'd32767)
sec_flag <= 1'b1;
else
sec_flag <= 1'b0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
flag <= 1'b0;
else if(start)
flag <= 1'b1;
else if(sec_cnt == alarm)
flag <= 1'b0;
else
flag <= flag;
always @(posedge clk or negedge rst_n)
if(!rst_n)
sec_cnt <= 32'd0;
else if(sec_flag)
sec_cnt <= sec_cnt + 1'b1;
else if(sec_cnt == alarm)
sec_cnt <= 32'd0;
else
sec_cnt <= sec_cnt;
assign int_pluse = (alarm == sec_cnt)? 1'b1:1'b0;
endmodule
3、tb书写
`timescale 1us/1ns
module tb_sec;
reg clk;
reg rst_n;
reg start;
reg [7:0] alarm;
wire int_pluse;
wire [31:0] sec_cnt;
initial begin
clk = 0;
rst_n = 0;
alarm = 8'd25;
start =0;
#100;
rst_n =1;
#100;
start =1;
#31
start =0;
@(posedge int_pluse ) begin
#10000;
start=1;
end
#31
start=0;
end
always # 15.259 clk =~clk;
sec sec_inst(
.clk(clk),
.rst_n(rst_n),
.start(start),
.alarm(alarm),
.int_pluse(int_pluse),
.sec_cnt(sec_cnt)
);
endmodule
4、仿真分析
根据题意仿真正确,仿真的时候周期为题意要求的32.768KHz,仿真结果与题意相符