abstractaccelerator/opene906/smart_run/logical/gpio/gpio_ctrl.v

346 lines
9.2 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; @21
module gpio_ctrl(
gpio_ext_porta,
gpio_ext_porta_rb,
gpio_int_polarity,
gpio_inten,
gpio_intmask,
gpio_intr,
gpio_intr_flag_int,
gpio_intr_int,
gpio_intrclk_en,
gpio_inttype_level,
gpio_ls_sync,
gpio_porta_ddr,
gpio_porta_dr,
gpio_porta_eoi,
gpio_raw_intstatus,
gpio_swporta_ctl,
gpio_swporta_ddr,
gpio_swporta_dr,
pclk,
pclk_intr,
presetn
);
// &Ports; @22
input [7:0] gpio_ext_porta;
input [7:0] gpio_int_polarity;
input [7:0] gpio_inten;
input [7:0] gpio_intmask;
input [7:0] gpio_inttype_level;
input gpio_ls_sync;
input [7:0] gpio_porta_eoi;
input [7:0] gpio_swporta_ctl;
input [7:0] gpio_swporta_ddr;
input [7:0] gpio_swporta_dr;
input pclk;
input pclk_intr;
input presetn;
output [7:0] gpio_ext_porta_rb;
output [7:0] gpio_intr;
output gpio_intr_flag_int;
output [7:0] gpio_intr_int;
output gpio_intrclk_en;
output [7:0] gpio_porta_ddr;
output [7:0] gpio_porta_dr;
output [7:0] gpio_raw_intstatus;
// &Regs; @23
reg [7:0] ed_int_d1;
reg [7:0] ed_out;
reg [7:0] gpio_ext_porta_int;
reg [7:0] gpio_ext_porta_rb;
reg [7:0] gpio_intr_ed_pm;
reg gpio_intrclk_en;
reg [7:0] gpio_porta_ddr;
reg [7:0] gpio_porta_dr;
reg [7:0] int_gpio_raw_intstatus;
reg [7:0] int_pre_in;
reg [7:0] int_s1;
reg [7:0] int_sy_in;
reg [7:0] intrclk_en;
reg [7:0] ls_int_in;
// &Wires; @24
wire [7:0] ed_rf;
wire [7:0] gpio_ext_porta;
wire [7:0] gpio_int_polarity;
wire [7:0] gpio_inten;
wire [7:0] gpio_intmask;
wire [7:0] gpio_intr;
wire gpio_intr_flag_int;
wire [7:0] gpio_intr_int;
wire gpio_intrclk_en_int;
wire [7:0] gpio_inttype_level;
wire gpio_ls_sync;
wire [7:0] gpio_porta_eoi;
wire [7:0] gpio_raw_intstatus;
wire [7:0] gpio_swporta_ctl;
wire [7:0] gpio_swporta_ctl_internal;
wire [7:0] gpio_swporta_ddr;
wire [7:0] gpio_swporta_dr;
wire [7:0] int_in;
wire pclk;
wire pclk_intr;
wire presetn;
// &Force("output", "gpio_intr"); @26
// &Force("output", "gpio_intr_int"); @27
// &Force("output", "gpio_raw_intstatus"); @28
// &Force("output", "gpio_porta_ddr"); @29
// gpio_intrclk_en output asserted if any bit of port
// a is enabled for edge sensitive interrupts or
// any bit of port a is enabled for level sensitive
// interrupts and level sensitive synchronisation
// is required.
integer type_i;
// &CombBeg; @37
always @( gpio_inttype_level[1:0]
or gpio_ls_sync
or gpio_inten[7:0]
or gpio_inttype_level[7:1])
begin
for(type_i = 0 ; type_i < 8 ; type_i=type_i+1)
begin
if(gpio_inten[type_i] == 1'b1)
if(gpio_inttype_level[type_i] == 1'b1)
intrclk_en[type_i] = 1'b1;
else
intrclk_en[type_i] = gpio_ls_sync;
else
intrclk_en[type_i] = 1'b0;
end
// &CombEnd; @49
end
assign gpio_intrclk_en_int = | intrclk_en;
always@(posedge pclk or negedge presetn)
begin
if(!presetn)
gpio_intrclk_en <= 1'b0;
else
gpio_intrclk_en <= gpio_intrclk_en_int;
end
// Input is inverted for falling edge or active low
// sensitive interrupts.
integer polarity_i;
// &CombBeg; @64
always @( gpio_ext_porta[1:0]
or gpio_int_polarity[7:0]
or gpio_ext_porta[7:0]
or gpio_int_polarity[1:0])
begin
gpio_ext_porta_int[7:0] = {8{1'b0}};
for(polarity_i = 0 ; polarity_i < 8 ; polarity_i=polarity_i+1)
begin
if(gpio_int_polarity[polarity_i] == 1'b0)
gpio_ext_porta_int[polarity_i] = ~gpio_ext_porta[polarity_i];
else
gpio_ext_porta_int[polarity_i] = gpio_ext_porta[polarity_i];
end
// &CombEnd; @73
end
// &CombBeg; @75
always @( gpio_ext_porta_int[7:0])
begin
int_sy_in[7:0] = {8{1'b0}};
int_sy_in[7:0] = gpio_ext_porta_int[7:0];
// &CombEnd; @78
end
// Meta-stabilty registers. Synchronize to pclk_intr.
always @(posedge pclk_intr or negedge presetn)
begin
if(!presetn)
int_s1[7:0] <= {8{1'b0}};
else
int_s1[7:0] <= int_sy_in[7:0];
end
always @(posedge pclk_intr or negedge presetn)
begin
if(!presetn)
int_pre_in[7:0] <= {8{1'b0}};
else
int_pre_in[7:0] <= int_s1;
end
assign int_in[7:0] = int_pre_in[7:0];
// edge detect circuitry.
always @(posedge pclk_intr or negedge presetn)
begin
if(!presetn)
ed_int_d1[7:0] <= {8{1'b0}};
else
ed_int_d1[7:0] <= int_in[7:0];
end
assign ed_rf[7:0] = int_in ^ ed_int_d1;
// Rising edge detect
integer ed_j;
// &CombBeg; @112
always @( ed_rf[7:0]
or int_in[7:0])
begin
ed_out[7:0] = {8{1'b0}};
for(ed_j = 0 ; ed_j < 8 ; ed_j=ed_j+1)
begin
ed_out[ed_j] = ed_rf[ed_j] & int_in[ed_j];
end
// &CombEnd; @119
end
// edge detect interrupt register pre-masking. If edge detection
// occurs at same time as write to interrupt clear register then
// write to interrupt clear register will not clear the interrupt.
// Interrupts can only be set when direction is input and in
// software mode.
assign gpio_swporta_ctl_internal[7:0] = gpio_swporta_ctl[7:0];
integer int_k;
always @(posedge pclk_intr or negedge presetn)
begin
if(!presetn)
gpio_intr_ed_pm[7:0] <= {8{1'b0}};
else
for(int_k = 0 ; int_k < 8 ; int_k=int_k+1)
begin
if(gpio_inten[int_k] == 1'b0)
gpio_intr_ed_pm[int_k] <= 1'b0;
else
if((ed_out[int_k] == 1'b1) &&
(gpio_inten[int_k] == 1'b1) &&
(gpio_swporta_ddr[int_k] == 1'b0) &&
(gpio_swporta_ctl_internal[int_k] == 1'b0))
gpio_intr_ed_pm[int_k] <= 1'b1;
else
if(gpio_porta_eoi[int_k] == 1'b1)
gpio_intr_ed_pm[int_k] <= 1'b0;
end
end
// Level senistive interrupts may pass through synchronization
// and debounce logic. Under S/W control.
// Interrupts can only be set when direction is input and in
// software mode.
integer lsa_k;
// &CombBeg; @155
always @( int_in[7:0]
or gpio_swporta_ddr[7:0]
or gpio_swporta_ctl_internal[2:0]
or gpio_ls_sync
or int_sy_in[7:0]
or gpio_swporta_ctl_internal[7:2])
begin
ls_int_in[7:0] = {8{1'b0}};
for(lsa_k = 0 ; lsa_k < 8 ; lsa_k=lsa_k+1)
begin
if(((gpio_swporta_ddr[lsa_k]) == 1'b1) ||
(gpio_swporta_ctl_internal[lsa_k] == 1'b1))
ls_int_in[lsa_k] = 0;
else
if(gpio_ls_sync == 1'b1)
ls_int_in[lsa_k] = int_in[lsa_k];
else
ls_int_in[lsa_k] = int_sy_in[lsa_k];
end
// &CombEnd; @168
end
// Level or edge sensitive interrupts
integer raw_l;
// &CombBeg; @173
always @( gpio_inten[7:3]
or gpio_intr_ed_pm[2:0]
or gpio_intr_ed_pm[7:1]
or gpio_inten[4:0]
or gpio_inttype_level[7:0]
or ls_int_in[7:0])
begin
int_gpio_raw_intstatus[7:0] = {8{1'b0}};
for(raw_l = 0 ; raw_l < 8 ; raw_l=raw_l+1)
begin
if(gpio_inten[raw_l] == 1'b0)
int_gpio_raw_intstatus[raw_l] = 0;
else
if(gpio_inttype_level[raw_l] == 1'b1)
int_gpio_raw_intstatus[raw_l] = gpio_intr_ed_pm[raw_l];
else
int_gpio_raw_intstatus[raw_l] = ls_int_in[raw_l];
end
// &CombEnd; @185
end
assign gpio_raw_intstatus[7:0] = int_gpio_raw_intstatus[7:0];
assign gpio_intr_int[7:0] = gpio_raw_intstatus[7:0] & ~gpio_intmask[7:0];
assign gpio_intr[7:0] = gpio_intr_int[7:0];
assign gpio_intr_flag_int = |gpio_intr_int[7:0];
// &CombBeg; @192
always @( gpio_swporta_dr[7:0])
begin
gpio_porta_dr[7:0] = {8{1'b0}};
gpio_porta_dr[7:0] = gpio_swporta_dr[7:0];
// &CombEnd; @195
end
// &CombBeg; @197
always @( gpio_swporta_ddr[7:0])
begin
gpio_porta_ddr[7:0] = {8{1'b0}};
gpio_porta_ddr[7:0] = gpio_swporta_ddr[7:0];
// &CombEnd; @200
end
integer rba_i;
// &CombBeg; @204
always @( gpio_swporta_dr[2:1]
or gpio_ext_porta[7:0]
or gpio_swporta_dr[7:0]
or gpio_porta_ddr[7:0])
begin
gpio_ext_porta_rb[7:0] = {8{1'b0}};
for(rba_i = 0 ; rba_i < 8 ; rba_i=rba_i+1)
begin
if(gpio_porta_ddr[rba_i] == 1'b1)
gpio_ext_porta_rb[rba_i] = gpio_swporta_dr[rba_i];
else
gpio_ext_porta_rb[rba_i] = gpio_ext_porta[rba_i];
end
// &CombEnd; @213
end
integer rbb_i;
// &ModuleEnd; @217
endmodule