ZG展锐数字IC岗编程题

本文详细介绍了如何使用Verilog RTL描述一个基于32.768KHz时钟的秒计数器,该计数器在接收到启动信号和配置的秒数到达时会产生中断。设计包括异步复位、启动信号控制、计数到预设值时的中断产生以及秒数的实时输出。在测试代码中,通过仿真展示了计数器的正确工作模式。
摘要由CSDN通过智能技术生成

题目:请用Verilog RTL描述如下图设计:以clk为基准,设计一个秒计数器,在指定的计数值产生中断,实时输出当前的秒数计数值。

<1>clk是时钟输入,频率为32.768KHz。

<2>rst_n是异步复位输入,低电平有效,复位整个系统,为高则整个系统开始工作,其上升沿已经同步于clk。

<3>start是启动信号,一个clk时钟周期的正脉冲,同步于clk。alarm[7:0]是配置信息,单位为秒,同步于clk。

<4>工作模式:收到start后,秒计数器sec_cnt从零开始以秒为单位来计数,计数到alarm[7:0]指定的数值时,产生一个int pluse(时钟周期的正脉冲),秒数计数器回零并停止。

根据题目进行思考:

1.设计一个1秒的计数器,可以利用系统时钟的频率,从0开始计数,当计数到32767时则完成1秒的计数。

2.异步复位,低电平有效即:

always@(posedge clk or negedge rst_n)

3.有一个statrt启动脉冲信号,当start=1时,开始进行计数。

4.alarm[7:0],即当sec_cnt=alarm时,int产生一个脉冲信号。假设alrm=3,即当计数满3秒的时候,int产生一个脉冲信号,秒数计数器返回0并停止。

分析:

1.由于start是一个脉冲信号,所以不能精确的控制计数的开始与结束,所以用一个cnt_en来控制计数的开始与结束。

2.用cnt_1s作为计数为1秒的计数器。

3.异步复位导致改变要慢一个时钟周期

波形图如下

module sec_cnt_top
#(
	parameter cnt_1s_max=16'd32767
)
(
	input wire clk,
	input wire rst_n,
	input wire start,
	input wire[7:0]alarm,
	output reg int1,
	output reg [31:0]sec_cnt
    );
	
	reg cnt_en;
	reg [14:0]cnt_1s;
	
always@(posedge clk or negedge rst_n)//使能端赋值
	if(rst_n==1'b0)
		cnt_en<=1'b0;
	else if(start==1'b1)
		cnt_en<=1'b1;
	else if((cnt_1s==cnt_1s_max)&&(sec_cnt==alarm))
		cnt_en<=1'b0;
	else
		cnt_en<=cnt_en;
		
always@(posedge clk or negedge rst_n)//时间为1s的计数器
	if(rst_n==1'b0)
		cnt_1s<=15'd0;
	else if(cnt_1s==cnt_1s_max)
		cnt_1s<=15'd0;
	else if(cnt_en==1'b1)
		cnt_1s<=cnt_1s+15'd1;
	else
		cnt_1s<=1'b0;

always@(posedge clk or negedge rst_n)//产生的时钟脉冲
	if(rst_n==1'b0)
		int1<=1'b0;
	else if((cnt_1s==cnt_1s_max)&&(sec_cnt==alarm))
		int1<=1'b1;
	else
		int1<=1'b0;
		
always@(posedge clk or negedge rst_n)//记录一共产生了多少个1s
	if(rst_n==1'b0)
		sec_cnt<=32'd0;
	else if((cnt_1s==cnt_1s_max)&&(sec_cnt==alarm))
		sec_cnt=32'd0;
	else if(cnt_1s==cnt_1s_max-1'b1)
		sec_cnt<=sec_cnt+32'd1;
	else
		sec_cnt<=sec_cnt;
	
endmodule

下面是测试代码

`timescale 1ns / 1ns

module tb_sec_cnt_top();
 
reg clk;
reg rst_n;
reg start;
reg [7:0]alarm;
wire int1;
wire [31:0]sec_cnt;
 
initial
	begin
		clk=1'b1;
		rst_n<=1'b0;
		start<=1'b0;
		alarm<=8'b0;
		#20 
		rst_n<=1'b1;
	end
initial
	begin
		#40
		start<=1'b1;
		alarm<=8'd3;
		#20
		start<=1'b0;
		#5000
		start<=1'b1;
		alarm<=8'd4;
		#20
		start<=1'b0;		
	end
always #10 clk=~clk;

sec_cnt_top
#(
.cnt_1s_max(16'd49)//便于仿真
)
sec_cnt_top_inst
(
.clk(clk),
.rst_n(rst_n),
.start(start),
.alarm(alarm),
.int1(int1),
.sec_cnt(sec_cnt)
);
 
endmodule

vivado仿真波形分析

各变量初值以及收到start脉冲时使能端为1

 当计数到alarm时,产生一个周期的时钟脉冲int1(为了仿真,故将计数最大值设置为49),记录一次结束后遍停止计数,等待下一次start信号出现再继续工作。

收到start信号,重新开始计数 

记满时产生一个周期的时钟脉冲

整体波形图如下(测试代码中第二次start改为#4000) 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值