103 lines
3.3 KiB
Systemverilog
103 lines
3.3 KiB
Systemverilog
|
/*
|
||
|
Copyright 2021 Blue Liang, liangkangnan@163.com
|
||
|
|
||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
you may not use this file except in compliance with the License.
|
||
|
You may obtain a copy of the License at
|
||
|
|
||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
Unless required by applicable law or agreed to in writing, software
|
||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
See the License for the specific language governing permissions and
|
||
|
limitations under the License.
|
||
|
*/
|
||
|
|
||
|
module timer_core (
|
||
|
input logic clk_i,
|
||
|
input logic rst_ni,
|
||
|
|
||
|
output logic irq_o,
|
||
|
|
||
|
input logic reg_we_i,
|
||
|
input logic reg_re_i,
|
||
|
input logic [31:0] reg_wdata_i,
|
||
|
input logic [ 3:0] reg_be_i,
|
||
|
input logic [31:0] reg_addr_i,
|
||
|
output logic [31:0] reg_rdata_o
|
||
|
);
|
||
|
|
||
|
import timer_reg_pkg::*;
|
||
|
|
||
|
timer_reg_pkg::timer_reg2hw_t reg2hw;
|
||
|
timer_reg_pkg::timer_hw2reg_t hw2reg;
|
||
|
|
||
|
logic start;
|
||
|
logic int_en;
|
||
|
logic int_pending;
|
||
|
logic mode;
|
||
|
logic [23:0] div_cont;
|
||
|
logic [31:0] count_q;
|
||
|
logic [31:0] value;
|
||
|
logic tick;
|
||
|
|
||
|
assign start = reg2hw.ctrl.en.q;
|
||
|
assign int_en = reg2hw.ctrl.int_en.q;
|
||
|
assign int_pending = reg2hw.ctrl.int_pending.q;
|
||
|
assign mode = reg2hw.ctrl.mode.q;
|
||
|
assign div_cont = reg2hw.ctrl.clk_div.q;
|
||
|
assign value = reg2hw.value.q;
|
||
|
|
||
|
// 当前计数值
|
||
|
assign hw2reg.count.d = count_q;
|
||
|
assign hw2reg.ctrl.int_pending.d = 1'b1;
|
||
|
assign hw2reg.ctrl.int_pending.de = (count_q == value) && int_en && start;
|
||
|
|
||
|
assign hw2reg.ctrl.en.d = 1'b0;
|
||
|
assign hw2reg.ctrl.en.de = (count_q == value) && (mode == 1'b0) && start;
|
||
|
|
||
|
assign irq_o = int_pending;
|
||
|
|
||
|
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||
|
if (!rst_ni) begin
|
||
|
count_q <= 32'h0;
|
||
|
end else begin
|
||
|
if (start) begin
|
||
|
if (tick) begin
|
||
|
count_q <= count_q + 1'b1;
|
||
|
if (count_q == value) begin
|
||
|
count_q <= 32'h0;
|
||
|
end
|
||
|
end
|
||
|
end else begin
|
||
|
count_q <= 32'h0;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
clk_div #(
|
||
|
.RATIO_WIDTH(24)
|
||
|
) u_clk_div (
|
||
|
.clk_i(clk_i),
|
||
|
.rst_ni(rst_ni || (~(count_q == value))),
|
||
|
.en_i(start),
|
||
|
.ratio_i(div_cont),
|
||
|
.clk_o(tick)
|
||
|
);
|
||
|
|
||
|
timer_reg_top u_timer_reg_top (
|
||
|
.clk_i (clk_i),
|
||
|
.rst_ni (rst_ni),
|
||
|
.reg2hw (reg2hw),
|
||
|
.hw2reg (hw2reg),
|
||
|
.reg_we (reg_we_i),
|
||
|
.reg_re (reg_re_i),
|
||
|
.reg_wdata (reg_wdata_i),
|
||
|
.reg_be (reg_be_i),
|
||
|
.reg_addr (reg_addr_i),
|
||
|
.reg_rdata (reg_rdata_o)
|
||
|
);
|
||
|
|
||
|
endmodule
|