目录
输入输出
input wire clk,
input wire rst,
input wire [31:0] data_i,
input wire [31:0] addr_i,
input wire we_i,
output reg [31:0] data_o, //输出
output wire int_sig_o //中断信号
内部寄存器
localparam REG_CTRL = 4'h0; //addr_i[3:0]对应的控制 控制字段
localparam REG_COUNT = 4'h4; //计数 控制字段
localparam REG_VALUE = 4'h8; //计数最大 控制字段
// [0]: timer enable
// [1]: timer int enable
// [2]: timer int pending, write 1 to clear it(中断发生等待响应)
// addr offset: 0x00
reg[31:0] timer_ctrl;
// timer current count, read only
// addr offset: 0x04
reg[31:0] timer_count;
// timer expired value
// addr offset: 0x08
reg[31:0] timer_value;
中断输出
//中断信号在中断发生等待响应和中断使能的情况下拉高
assign int_sig_o = ((timer_ctrl[2] == 1'b1) && (timer_ctrl[1] == 1'b1))? 1'b1: 1'b0;
写寄存器
//写寄存器
always @(posedge clk ) begin
if(rst==1'b0)begin
timer_ctrl<=32'b0;
timer_value<=32'b0;
end else begin
if(we_i==1'b1)begin
case (addr_i[3:0])
REG_CTRL: begin
//计时器使能克计时器中断使能直接赋值 data_i[2]=1即已经响应拉低timer_ctrl[2]
timer_ctrl<= {timer_ctrl[31:3],(timer_ctrl[2] & (~data_i[2])),data_i[1:0]};
end
REG_VALUE: begin
timer_value<=data_i;
end
endcase
end else begin//如果计数达到最大置并且定时器使能(只有使能才会计数)
if((timer_count==timer_value)&&(timer_ctrl[0]==1'b1))begin
timer_ctrl[0]=1'b0;
timer_ctrl[2]=1'b1;
end
end
end
end
计数器
//计数器
always @(posedge clk) begin
if (rst==1'b0) begin
timer_count<=32'b0;
end else begin
if(timer_ctrl[0]==1'b1)begin
timer_count<=timer_count+1'b1;
if(timer_count==timer_value)begin
timer_count<=32'b0;
end
end else begin
timer_count<=32'b0;
end
end
end
读寄存器(组合逻辑)
//计数器
always @(posedge clk) begin
if (rst==1'b0) begin
timer_count<=32'b0;
end else begin
if(timer_ctrl[0]==1'b1)begin
timer_count<=timer_count+1'b1;
if(timer_count==timer_value)begin
timer_count<=32'b0;
end
end else begin
timer_count<=32'b0;
end
end
end
仿真
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/07/20 09:46:43
// Design Name:
// Module Name: timersim
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module timersim(
);
reg clk;
reg rst;
reg [31:0] data_i;
reg [31:0] addr_i;
reg we_i;
wire [31:0] data_o; //输出
wire int_sig_o; //中断信号wire
localparam REG_CTRL = 4'h0; //addr_i[3:0]对应的控制 控制字段
localparam REG_COUNT = 4'h4; //计数 控制字段
localparam REG_VALUE = 4'h8; //计数最大 控制字段
timer timer_init(
.clk(clk),
.rst(rst),
.data_i(data_i),
.addr_i(addr_i),
.we_i(we_i),
.data_o(data_o), //输出
.int_sig_o(int_sig_o) //中断信号
);
initial begin
clk=1'b1;
rst=1'b0;
we_i=1'b0;
#20
rst=1'b1;
#20
we_i=1'b1;
addr_i={28'b0,REG_VALUE};
data_i=32'd15;
#20
addr_i={28'b0,REG_CTRL};
data_i={30'b0,2'b11};
#60
we_i<=1'b0;
addr_i={28'b0,REG_CTRL};//读REG_CTRL
#20
addr_i={28'b0,REG_VALUE};//读REG_VALUE
end
always begin
#10
clk=~clk;
end
endmodule