abstractaccelerator/opene906/smart_run/logical/pmu/pmu.v

543 lines
14 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.
*/
// &Depend("environment.h"); @21
// &Depend("cpu_cfig.h"); @22
// &ModuleBeg; @24
module pmu(
apb_pmu_paddr,
apb_pmu_penable,
apb_pmu_psel,
apb_pmu_pwdata,
apb_pmu_pwrite,
biu_pad_lpmd_b,
corec_pmu_sleep_out,
cpu_clk,
gate_en0,
gate_en1,
had_pad_wakeup_req_b,
i_pad_cpu_jtg_rst_b,
i_pad_jtg_tclk,
intraw_vld,
pad_cpu_rst_b,
pad_had_jtg_tap_en,
pad_had_jtg_tms_i,
pad_had_jtg_trst_b,
pad_had_jtg_trst_b_pre,
pg_reset_b,
pmu_apb_prdata,
pmu_clk,
pmu_corec_isolation,
pmu_corec_sleep_in,
sys_rst
);
// &Ports; @25
input [11:0] apb_pmu_paddr;
input apb_pmu_penable;
input apb_pmu_psel;
input [31:0] apb_pmu_pwdata;
input apb_pmu_pwrite;
input [1 :0] biu_pad_lpmd_b;
input corec_pmu_sleep_out;
input cpu_clk;
input had_pad_wakeup_req_b;
input i_pad_cpu_jtg_rst_b;
input i_pad_jtg_tclk;
input intraw_vld;
input pad_cpu_rst_b;
input pad_had_jtg_tap_en;
input pad_had_jtg_tms_i;
input pad_had_jtg_trst_b_pre;
input pmu_clk;
input sys_rst;
output gate_en0;
output gate_en1;
output pad_had_jtg_trst_b;
output pg_reset_b;
output [31:0] pmu_apb_prdata;
output pmu_corec_isolation;
output pmu_corec_sleep_in;
// &Regs; @26
reg [31:0] counter;
reg counter_en_ff;
reg [31:0] counter_load;
reg [31:0] ctrl_reg;
reg [2 :0] cur_state;
reg debug_pending;
reg event_ff;
reg event_pending;
reg [2 :0] next_state;
reg [2 :0] pg_next_state;
reg [2 :0] pg_state;
reg [31:0] pmu_apb_prdata;
// &Wires; @27
wire [11:0] apb_pmu_paddr;
wire apb_pmu_penable;
wire apb_pmu_psel;
wire [31:0] apb_pmu_pwdata;
wire apb_pmu_pwrite;
wire [1 :0] biu_pad_lpmd_b;
wire corec_pmu_sleep_out;
wire counter_en;
wire cpu_clk;
wire debug_ctl_en;
wire debug_vld;
wire debug_vld_pre;
wire debug_wake_vld;
wire doze_mode;
wire event_ctl_en;
wire event_vld;
wire gate_en0;
wire gate_en1;
wire had_pad_wakeup_req_b;
wire i_pad_cpu_jtg_rst_b;
wire i_pad_jtg_tclk;
wire intraw_vld;
wire load_cnt_en;
wire low_power_dis;
wire low_power_dis_pre;
wire lpmd_en;
wire lpmd_en_ff;
wire pad_cpu_rst_b;
wire pad_had_jtg_tap_en;
wire pad_had_jtg_tms_i;
wire pad_had_jtg_trst_b;
wire pad_had_jtg_trst_b_pre;
wire pad_vic_event_vld;
wire pg_reset_b;
wire pmu_clk;
wire pmu_corec_isolation;
wire pmu_corec_sleep_in;
wire pmu_debug_wakeup;
wire pmu_event_wakeup;
wire pmu_wakeup;
wire pmu_wic_wakeup;
wire stop_mode;
wire sys_rst;
wire wait_mode;
wire wic_ctl_en;
parameter IDLE = 3'b000;
parameter WAIT = 3'b001;
parameter DOZE = 3'b010;
parameter STOP = 3'b011;
parameter WAIT_AWAKE = 3'b100;
parameter PG_IDLE = 3'b000;
parameter PG_RESET_ON = 3'b001;
parameter PG_ISO_ON = 3'b010;
parameter PG_POWER_OFF_REQ = 3'b011;
parameter PG_POWER_OFF = 3'b100;
parameter PG_POWER_ON = 3'b101;
parameter PG_ISO_OFF = 3'b110;
parameter PG_RESET_OFF = 3'b111;
assign low_power_dis_pre = (biu_pad_lpmd_b[1:0] == 2'b11);
assign lpmd_en = (biu_pad_lpmd_b[1:0] != 2'b11) ;
////////////sync /////////////////////
// &Instance("sync", "x_cpu2pmu_sync1"); @58
sync x_cpu2pmu_sync1 (
.fast_clk (cpu_clk ),
.in (lpmd_en ),
.out (lpmd_en_ff ),
.pad_cpu_rst_b (pad_cpu_rst_b),
.slow_clk (pmu_clk )
);
// &Connect( .in ( lpmd_en ), @59
// .out ( lpmd_en_ff ), @60
// .fast_clk ( cpu_clk ), @61
// .slow_clk ( pmu_clk ) @62
// ); @63
// &Instance("sync", "x_cpu2pmu_sync2"); @69
sync x_cpu2pmu_sync2 (
.fast_clk (cpu_clk ),
.in (low_power_dis_pre),
.out (low_power_dis ),
.pad_cpu_rst_b (pad_cpu_rst_b ),
.slow_clk (pmu_clk )
);
// &Connect( .in ( low_power_dis_pre ), @70
// .out ( low_power_dis ), @71
// .fast_clk ( cpu_clk ), @72
// .slow_clk ( pmu_clk ) @73
// ); @74
//------------------------------------------------
//WRITE CTRL REG
//------------------------------------------------
always @ (posedge pmu_clk or negedge pad_cpu_rst_b)
begin
if (!pad_cpu_rst_b)
begin
ctrl_reg[31:0] <= 32'b0;
end
else if (apb_pmu_psel && apb_pmu_pwrite && apb_pmu_penable)
begin
if (!apb_pmu_paddr[11:0] )
ctrl_reg[31:0] <= apb_pmu_pwdata[31:0];
else if (apb_pmu_paddr[11:0] == 12'h4 )
counter_load[31:0] <= apb_pmu_pwdata[31:0];
end
end
//------------------------------------------------
//READ CTRL REG
//------------------------------------------------
// &CombBeg; @99
always @( apb_pmu_paddr[11:0]
or ctrl_reg[3:0]
or apb_pmu_psel
or apb_pmu_pwrite
or counter[31:0])
begin
if (apb_pmu_psel && !apb_pmu_pwrite)
begin
if(!apb_pmu_paddr[11:0] )
pmu_apb_prdata[31:0] = {28'b0,ctrl_reg[3:0]};
else if (apb_pmu_paddr[11:0] == 12'h4 )
pmu_apb_prdata[31:0] = counter[31:0];
else
pmu_apb_prdata[31:0] = 32'b0;
end
// &CombEnd; @109
end
assign wic_ctl_en = ctrl_reg[0];
assign event_ctl_en = ctrl_reg[1];
assign debug_ctl_en = ctrl_reg[2];
assign counter_en = ctrl_reg[3];
//event counter
always @(posedge pmu_clk or negedge pad_cpu_rst_b)
begin
if(!pad_cpu_rst_b)
begin
counter_en_ff <=0;
end
else
begin
counter_en_ff <=counter_en ;
end
end
assign load_cnt_en= (counter_en && !counter_en_ff)
|| !(|counter[31:0]);
always @(posedge pmu_clk or negedge pad_cpu_rst_b)
begin
if(!pad_cpu_rst_b)
begin
counter[31:0] <= 32'h0;
end
else if (load_cnt_en)
begin
counter[31:0] <= counter_load[31:0];
end
else if (counter_en)
counter[31:0] <= counter[31:0] -1'b1;
else
counter[31:0] <= counter[31:0];
end
assign pad_vic_event_vld = (counter[31:0] == 32'b0) && counter_en;
assign pmu_wic_wakeup = intraw_vld && wic_ctl_en && lpmd_en_ff ;
// event_wakeup
assign event_vld = pad_vic_event_vld && !event_ff && lpmd_en_ff ;
always @(posedge pmu_clk or negedge pad_cpu_rst_b)
begin
if (!pad_cpu_rst_b)
event_ff <= 1'b0;
else
event_ff <= pad_vic_event_vld;
end
always @(posedge pmu_clk or negedge pad_cpu_rst_b)
begin
if (!pad_cpu_rst_b)
event_pending <= 1'b0;
else if (event_vld)
event_pending <= 1'b1;
else if (low_power_dis)
event_pending <= 1'b0;
end
assign pmu_event_wakeup = event_pending && event_ctl_en ;
//debug wake up
// &Instance("tap2_sm", "x_tap2_sm"); @180
tap2_sm x_tap2_sm (
.debug_wake_vld (debug_wake_vld ),
.pad_had_jtg_tap_en (pad_had_jtg_tap_en ),
.tclk (i_pad_jtg_tclk ),
.tms_i (pad_had_jtg_tms_i ),
.trst_b (i_pad_cpu_jtg_rst_b)
);
// &Connect(.tclk (i_pad_jtg_tclk ), @181
// // .trst_b (i_pad_jtg_trst_b ), @182
// .trst_b (i_pad_cpu_jtg_rst_b ), @183
// .tms_i (pad_had_jtg_tms_i ) @184
// ); @185
assign debug_vld_pre = (debug_wake_vld || !had_pad_wakeup_req_b) && lpmd_en_ff;
// &Instance("px_had_sync", "x_jtag2pmu_sync"); @193
px_had_sync x_jtag2pmu_sync (
.clk1 (i_pad_jtg_tclk ),
.clk2 (pmu_clk ),
.rst1_b (pad_had_jtg_trst_b_pre),
.rst2_b (pad_cpu_rst_b ),
.sync_in (debug_vld_pre ),
.sync_out (debug_vld )
);
// &Connect(.clk1 (i_pad_jtg_tclk ), @194
// .clk2 (pmu_clk ), @195
// .rst1_b (pad_had_jtg_trst_b_pre ), @196
// .rst2_b (pad_cpu_rst_b ), @197
// .sync_in (debug_vld_pre ), @198
// .sync_out (debug_vld ) @199
// ); @200
always @(posedge pmu_clk or negedge pad_cpu_rst_b)
begin
if (!pad_cpu_rst_b)
debug_pending <= 1'b0;
else if (debug_vld)
debug_pending <= 1'b1;
else if (low_power_dis)
debug_pending <= 1'b0;
end
//assign pad_had_jdb_req_b = !debug_pending;
assign pmu_debug_wakeup = debug_pending && debug_ctl_en ;
/////
assign pmu_wakeup = pmu_event_wakeup || pmu_wic_wakeup || pmu_debug_wakeup ;
//-----------------------------------------
// PMU FSM
//-----------------------------------------
always @(posedge pmu_clk or negedge pad_cpu_rst_b)
begin
if (!pad_cpu_rst_b)
cur_state[2:0] <= IDLE;
else
cur_state[2:0] <= next_state[2:0];
end
//assign doze_mode = ( biu_pad_lpmd_b[1:0] == 2'b10);
//assign wait_mode = ( biu_pad_lpmd_b[1:0] == 2'b01);
//assign stop_mode = ( biu_pad_lpmd_b[1:0] == 2'b00);
assign doze_mode = 1'b0;
assign wait_mode = 1'b0;
assign stop_mode = 1'b0;
// &CombBeg; @246
always @( cur_state
or pmu_wakeup
or pg_state[2:0]
or biu_pad_lpmd_b[1:0]
or doze_mode
or stop_mode
or wait_mode)
begin
case(cur_state)
IDLE:
begin
if(doze_mode )
begin
next_state = DOZE;
end
else if(wait_mode )
begin
next_state = WAIT;
end
else if(stop_mode )
begin
next_state = STOP;
end
else
begin
next_state = IDLE;
end
end
DOZE:
begin
if(pmu_wakeup)
begin
next_state = WAIT_AWAKE;
end
else
begin
next_state = DOZE;
end
end
WAIT:
begin
if(pmu_wakeup)
begin
next_state = WAIT_AWAKE;
end
else
begin
next_state = WAIT;
end
end
STOP://////// more states more pg crtl signal
begin
if(pg_state[2:0]==3'b111)
begin
next_state = WAIT_AWAKE;
end
else
begin
next_state = STOP;
end
end
WAIT_AWAKE:
begin
if(biu_pad_lpmd_b[1:0] == 2'b11)
begin
next_state = IDLE;
end
else
begin
next_state = WAIT_AWAKE;
end
end
endcase
// &CombEnd; @317
end
assign gate_en0 = (cur_state[2:0] == IDLE) || (cur_state[2:0] == WAIT_AWAKE);
assign gate_en1 = (cur_state[2:0] == WAIT) || (cur_state[2:0] == IDLE)
|| (cur_state[2:0] == WAIT_AWAKE);
//----------------------------------------
// Power Gating FSM
//-----------------------------------------
always @(posedge pmu_clk or negedge pad_cpu_rst_b)
begin
if (!pad_cpu_rst_b)
pg_state[2:0] <= PG_IDLE;
else
pg_state[2:0] <= pg_next_state[2:0];
end
// &CombBeg; @337
always @( pmu_wakeup
or pg_state[2:0]
or corec_pmu_sleep_out
or cur_state[2:0])
begin
case(pg_state[2:0])
PG_IDLE:
begin
if(cur_state[2:0] == STOP)
pg_next_state = PG_RESET_ON;
else
pg_next_state = PG_IDLE;
end
PG_RESET_ON:
pg_next_state = PG_ISO_ON;
PG_ISO_ON:
pg_next_state = PG_POWER_OFF_REQ;
PG_POWER_OFF_REQ:
begin
if(corec_pmu_sleep_out)
pg_next_state = PG_POWER_OFF;
else
pg_next_state = PG_POWER_OFF_REQ;
end
PG_POWER_OFF:
begin
if(pmu_wakeup)
pg_next_state = PG_POWER_ON;
else
pg_next_state = PG_POWER_OFF;
end
PG_POWER_ON:
pg_next_state = PG_ISO_OFF;
PG_ISO_OFF:
pg_next_state = PG_RESET_OFF;
PG_RESET_OFF:
pg_next_state = IDLE;
endcase
// &CombEnd @371
end
assign pmu_corec_sleep_in = pg_state[2:0] == PG_POWER_OFF_REQ
|| pg_state[2:0] == PG_POWER_OFF;
assign pmu_corec_isolation = pg_state[2:0] == PG_ISO_ON
|| pg_state[2:0] == PG_POWER_OFF_REQ
|| pg_state[2:0] == PG_POWER_OFF
|| pg_state[2:0] == PG_POWER_ON
|| pg_state[2:0] == PG_ISO_OFF;
assign pg_reset_b = pg_state[2:0] == PG_IDLE
&& pad_cpu_rst_b & sys_rst;
assign pad_had_jtg_trst_b = pg_state[2:0] == PG_IDLE
&& pad_had_jtg_trst_b_pre;
// &ModuleEnd; @392
endmodule