abstractaccelerator/opene906/smart_run/logical/timer/timer.v

592 lines
16 KiB
Verilog

/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd.
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.
*/
// &ModuleBeg; @23
module timer(
paddr,
pclk,
penable,
prdata,
presetn,
psel,
pwdata,
pwrite,
timer_int
);
// &Ports; @24
input [15:0] paddr;
input pclk;
input penable;
input presetn;
input psel;
input [31:0] pwdata;
input pwrite;
output [31:0] prdata;
output [3 :0] timer_int;
// &Regs; @25
reg [31:0] prdata;
reg [2 :0] timer_1_control_reg;
reg [31:0] timer_1_load_count;
reg timer_1_raw_int_status;
reg [2 :0] timer_2_control_reg;
reg [31:0] timer_2_load_count;
reg timer_2_raw_int_status;
reg [2 :0] timer_3_control_reg;
reg [31:0] timer_3_load_count;
reg timer_3_raw_int_status;
reg [2 :0] timer_4_control_reg;
reg [31:0] timer_4_load_count;
reg timer_4_raw_int_status;
// &Wires; @26
wire [15:0] paddr;
wire pclk;
wire presetn;
wire psel;
wire [31:0] pwdata;
wire pwrite;
wire [31:0] timer_1_current_value;
wire timer_1_int_clear;
wire timer_1_int_status;
wire timer_1_interrupt;
wire [31:0] timer_2_current_value;
wire timer_2_int_clear;
wire timer_2_int_status;
wire timer_2_interrupt;
wire [31:0] timer_3_current_value;
wire timer_3_int_clear;
wire timer_3_int_status;
wire timer_3_interrupt;
wire [31:0] timer_4_current_value;
wire timer_4_int_clear;
wire timer_4_int_status;
wire timer_4_interrupt;
wire [3 :0] timer_int;
wire timers_int_clear;
// &Force("bus","paddr",15,0); @28
// &Force("bus","pwdata",31,0); @29
// &Force("input","penable"); @30
// &Force("output","prdata"); @31
// &Force("bus","prdata",31,0); @32
// &Force("output","timer_int"); @33
// &Force("bus","timer_int",3,0); @34
// &Instance("counter", "timer_1"); @36
counter timer_1 (
.interrupt (timer_1_interrupt ),
.pclk (pclk ),
.presetn (presetn ),
.timer_current_value (timer_1_current_value ),
.timer_enable (timer_1_control_reg[0]),
.timer_load_count (timer_1_load_count ),
.timer_mode (timer_1_control_reg[1])
);
// &Connect(.pclk (pclk ), @37
// .presetn (presetn ), @38
// .timer_enable (timer_1_control_reg[0] ), @39
// .timer_mode (timer_1_control_reg[1] ), @40
// .timer_load_count (timer_1_load_count ), @41
// .timer_current_value (timer_1_current_value ), @42
// .interrupt (timer_1_interrupt ) @43
// ); @44
// &Instance("counter", "timer_2"); @46
counter timer_2 (
.interrupt (timer_2_interrupt ),
.pclk (pclk ),
.presetn (presetn ),
.timer_current_value (timer_2_current_value ),
.timer_enable (timer_2_control_reg[0]),
.timer_load_count (timer_2_load_count ),
.timer_mode (timer_2_control_reg[1])
);
// &Connect(.pclk (pclk ), @47
// .presetn (presetn ), @48
// .timer_enable (timer_2_control_reg[0] ), @49
// .timer_mode (timer_2_control_reg[1] ), @50
// .timer_load_count (timer_2_load_count ), @51
// .timer_current_value (timer_2_current_value ), @52
// .interrupt (timer_2_interrupt ) @53
// ); @54
// &Instance("counter", "timer_3"); @56
counter timer_3 (
.interrupt (timer_3_interrupt ),
.pclk (pclk ),
.presetn (presetn ),
.timer_current_value (timer_3_current_value ),
.timer_enable (timer_3_control_reg[0]),
.timer_load_count (timer_3_load_count ),
.timer_mode (timer_3_control_reg[1])
);
// &Connect(.pclk (pclk ), @57
// .presetn (presetn ), @58
// .timer_enable (timer_3_control_reg[0] ), @59
// .timer_mode (timer_3_control_reg[1] ), @60
// .timer_load_count (timer_3_load_count ), @61
// .timer_current_value (timer_3_current_value ), @62
// .interrupt (timer_3_interrupt ) @63
// ); @64
// &Instance("counter", "timer_4"); @66
counter timer_4 (
.interrupt (timer_4_interrupt ),
.pclk (pclk ),
.presetn (presetn ),
.timer_current_value (timer_4_current_value ),
.timer_enable (timer_4_control_reg[0]),
.timer_load_count (timer_4_load_count ),
.timer_mode (timer_4_control_reg[1])
);
// &Connect(.pclk (pclk ), @67
// .presetn (presetn ), @68
// .timer_enable (timer_4_control_reg[0] ), @69
// .timer_mode (timer_4_control_reg[1] ), @70
// .timer_load_count (timer_4_load_count ), @71
// .timer_current_value (timer_4_current_value ), @72
// .interrupt (timer_4_interrupt ) @73
// ); @74
//==========================================================
// APB PWDATA
//==========================================================
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
timer_1_load_count <= 32'b0;
timer_1_control_reg <= 3'b0;
timer_2_load_count <= 32'b0;
timer_2_control_reg <= 3'b0;
timer_3_load_count <= 32'b0;
timer_3_control_reg <= 3'b0;
timer_4_load_count <= 32'b0;
timer_4_control_reg <= 3'b0;
end
else
begin
if(psel && pwrite && penable)
begin
case(paddr[7:2])
6'b000000:
begin
timer_1_load_count <= pwdata;
end
6'b000010:
begin
timer_1_control_reg <= pwdata[2:0];
end
6'b000101:
begin
timer_2_load_count <= pwdata;
end
6'b000111:
begin
timer_2_control_reg <= pwdata[2:0];
end
6'b001010:
begin
timer_3_load_count <= pwdata;
end
6'b001100:
begin
timer_3_control_reg <= pwdata[2:0];
end
6'b001111:
begin
timer_4_load_count <= pwdata;
end
6'b010001:
begin
timer_4_control_reg <= pwdata[2:0];
end
endcase
end
end
end
//==========================================================
// APB PRDATA
//==========================================================
always @(posedge pclk)
begin
if(psel && !pwrite)
begin
if (!penable)
begin
case(paddr[7:2])
6'b000000:
begin
prdata <= timer_1_load_count;
end
6'b000001:
begin
prdata <= timer_1_current_value;
end
6'b000010:
begin
prdata <= {29'b0, timer_1_control_reg};
end
6'b000011:
begin
prdata <= 32'b0;
end
6'b000100:
begin
prdata <= {31'b0, timer_1_int_status};
end
6'b000101:
begin
prdata <= timer_2_load_count;
end
6'b000110:
begin
prdata <= timer_2_current_value;
end
6'b000111:
begin
prdata <= {29'b0, timer_2_control_reg};
end
6'b001000:
begin
prdata <= 32'b0;
end
6'b001001:
begin
prdata <= {31'b0, timer_2_int_status};
end
6'b001010:
begin
prdata <= timer_3_load_count;
end
6'b001011:
begin
prdata <= timer_3_current_value;
end
6'b001100:
begin
prdata <= {29'b0, timer_3_control_reg};
end
6'b001101:
begin
prdata <= 32'b0;
end
6'b001110:
begin
prdata <= {31'b0, timer_3_int_status};
end
6'b001111:
begin
prdata <= timer_4_load_count;
end
6'b010000:
begin
prdata <= timer_4_current_value;
end
6'b010001:
begin
prdata <= {29'b0, timer_4_control_reg};
end
6'b010010:
begin
prdata <= 32'b0;
end
6'b010011:
begin
prdata <= {31'b0, timer_4_int_status};
end
6'b101000:
begin
prdata <= {28'b0, timer_int};
end
6'b101001:
begin
prdata <= 32'b0;
end
6'b101010:
begin
prdata <= {28'b0, timer_4_raw_int_status, timer_3_raw_int_status, timer_2_raw_int_status, timer_1_raw_int_status};
end
default:
begin
prdata <= 32'bx;
end
endcase
end
else
begin
prdata <= 32'bx;
end
end
end
assign timer_int = {timer_4_int_status, timer_3_int_status, timer_2_int_status, timer_1_int_status};
//==========================================================
// Clear Interrupt when reads EOI
//==========================================================
assign timer_1_int_clear = (paddr[7:2] == 6'b000011) && psel && !pwrite;
assign timer_2_int_clear = (paddr[7:2] == 6'b001000) && psel && !pwrite;
assign timer_3_int_clear = (paddr[7:2] == 6'b001101) && psel && !pwrite;
assign timer_4_int_clear = (paddr[7:2] == 6'b010010) && psel && !pwrite;
assign timers_int_clear = (paddr[7:2] == 6'b101001) && psel && !pwrite;
//==========================================================
// Timer 1 interrupt set and clear
//==========================================================
assign timer_1_int_status = timer_1_raw_int_status && !timer_1_control_reg[2];
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
timer_1_raw_int_status <= 1'b0;
end
else
begin
if(timer_1_control_reg[0])
begin
if(timer_1_interrupt)
begin
timer_1_raw_int_status <= 1'b1;
end
else
begin
if(timer_1_int_clear || timers_int_clear)
begin
timer_1_raw_int_status <= 1'b0;
end
end
end
else
begin
timer_1_raw_int_status <= 1'b0;
end
end
end
//==========================================================
// Timer 2 interrupt set and clear
//==========================================================
assign timer_2_int_status = timer_2_raw_int_status && !timer_2_control_reg[2];
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
timer_2_raw_int_status <= 1'b0;
end
else
begin
if(timer_2_control_reg[0])
begin
if(timer_2_interrupt)
begin
timer_2_raw_int_status <= 1'b1;
end
else
begin
if(timer_2_int_clear || timers_int_clear)
begin
timer_2_raw_int_status <= 1'b0;
end
end
end
else
begin
timer_2_raw_int_status <= 1'b0;
end
end
end
//==========================================================
// Timer 3 interrupt set and clear
//==========================================================
assign timer_3_int_status = timer_3_raw_int_status && !timer_3_control_reg[2];
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
timer_3_raw_int_status <= 1'b0;
end
else
begin
if(timer_3_control_reg[0])
begin
if(timer_3_interrupt)
begin
timer_3_raw_int_status <= 1'b1;
end
else
begin
if(timer_3_int_clear || timers_int_clear)
begin
timer_3_raw_int_status <= 1'b0;
end
end
end
else
begin
timer_3_raw_int_status <= 1'b0;
end
end
end
//==========================================================
// Timer 4 interrupt set and clear
//==========================================================
assign timer_4_int_status = timer_4_raw_int_status && !timer_4_control_reg[2];
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
timer_4_raw_int_status <= 1'b0;
end
else
begin
if(timer_4_control_reg[0])
begin
if(timer_4_interrupt)
begin
timer_4_raw_int_status <= 1'b1;
end
else
begin
if(timer_4_int_clear || timers_int_clear)
begin
timer_4_raw_int_status <= 1'b0;
end
end
end
else
begin
timer_4_raw_int_status <= 1'b0;
end
end
end
// &ModuleEnd; @385
endmodule
module counter(
interrupt,
pclk,
presetn,
timer_current_value,
timer_enable,
timer_load_count,
timer_mode
);
// &Ports; @24
input pclk;
input presetn;
input timer_enable;
input [31:0] timer_load_count;
input timer_mode;
output interrupt;
output [31:0] timer_current_value;
// &Regs; @25
reg [31:0] counter;
reg interrupt;
reg timer_enable_flop;
// &Wires; @26
wire load_cnt_en;
wire pclk;
wire presetn;
wire [31:0] timer_current_value;
wire timer_enable;
wire [31:0] timer_load_count;
wire timer_mode;
//==========================================================
// Counter
//==========================================================
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
timer_enable_flop <=0;
end
else
begin
timer_enable_flop <=timer_enable ;
end
end
assign load_cnt_en= (timer_enable && !timer_enable_flop)
|| !(|counter[31:0]);
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
counter[31:0] <=32'hffffffff;
end
else if(load_cnt_en)
begin
if(timer_mode)
begin
counter[31:0]<=timer_load_count[31:0];
end
else
begin
counter[31:0]<=32'hffffffff;
end
end
else if (timer_enable)
begin
counter[31:0]<=counter[31:0]-1'b1;
end
else
begin
counter[31:0]<=counter[31:0];
end
end
assign timer_current_value[31:0]=counter[31:0];
//==========================================================
// Interrupt sigals
//==========================================================
//internel interrupt
always @(posedge pclk or negedge presetn)
begin
if(!presetn)
begin
interrupt <=1'b0;
end
else if(!{|counter[31:0]})
begin
interrupt <=1'b1;
end
else
begin
interrupt<=1'b0 ;
end
end
// &ModuleEnd; @94
endmodule