首先需要分析题意,设计出模块的输入和输出:
1.此题中的32.768Khz是个很有意思的频率,在日常使用中,32.768Khz比较容易分频以便于产生1s的时钟频率,1s/(1/32768)=32768,对于32.768Khz计数一秒钟需要计数32768个时钟周期=2^15,设置一个15位的计数器,当其溢出时即是1s。
2.异步复位低电平有效,注意题中提及已经与时钟上升沿同步,不需要进行异步复位同步释放的处理。
3.start信号只持续一个时钟周期,所以需要产生计数使能信号
4.计数到预定值时,产生一个时钟周期的int_pluse,计数器清零并停止。
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Engineer: connor jiao // Create Date: 10:45 2020/6/14 // Design Name: // Module Name: // Function : 请用Verilog RTL描述如下图设计:以clk为基准,设计一个秒计数器,在指定的计数值产生中断,实时输出当前的秒数计数值。(紫光展锐数字IC岗) //<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(时钟周期的正脉冲),秒数计数器回零并停止。 // Revision 0.01 - File Created // Additional Comments: ////////////////////////////////////////////////////////////////////////////////// module seconds_counter( clk, rst_n, start, alarm, int_pluse, sec_cnt ); input clk; input rst_n; input start; input [7:0]alarm; output reg int_pluse; output reg [7:0]sec_cnt; // reg [7:0]alarm_r; reg [14:0]cnt1s; //对输入的信号进行寄存,防止操作过程中发生改变 always@(posedge clk or negedge rst_n) begin if(!rst_n) alarm_r<=8'd0; else if(start) alarm_r<=alarm; else alarm_r<=alarm_r; end //cnt_en reg cnt_en; always@(posedge clk or negedge rst_n) begin if(!rst_n) cnt_en<=1'b0; else if(start==1'b1) cnt_en<=1'b1; else if(sec_cnt==alarm_r&&cnt1s==32767) cnt_en<=1'b0; else cnt_en<=cnt_en; end // always@(posedge clk or negedge rst_n) begin if(!rst_n) cnt1s<='d0; else if(cnt_en) cnt1s<=cnt1s+1'b1; else cnt1s<='d0; end always@(posedge clk or negedge rst_n) begin if(!rst_n) sec_cnt<='d0; else if(sec_cnt==alarm_r&&cnt1s==32767) sec_cnt<='d0;//计数满清零,cnt_en控制计数满停止 else if(cnt1s==32767) sec_cnt<=sec_cnt+1'b1; else sec_cnt<=sec_cnt; end always@(posedge clk or negedge rst_n) begin if(!rst_n) int_pluse<=1'b0; else if(sec_cnt==alarm_r&&cnt1s==32767) int_pluse<=1'b1; else int_pluse<=1'b0; end endmodule
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Engineer: connor jiao // Create Date: // Design Name: // Module Name: // Function : // Revision 0.01 - File Created // Additional Comments: ////////////////////////////////////////////////////////////////////////////////// module seconds_counter_tb(); reg clk; reg rst_n; reg start; reg [7:0]alarm; wire int_pluse; wire [7:0]sec_cnt; seconds_counter seconds_counter( .clk(clk), .rst_n(rst_n), .start(start), .alarm(alarm), .int_pluse(int_pluse), .sec_cnt(sec_cnt) ); initial clk=0; always #1 clk=~clk; initial begin rst_n=0; alarm=0; start=0; #201; rst_n=1; #201; start=1'b1; alarm=8'd13; #2; start=1'b0; end endmodule