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,仿真結果與題意相符