rtl:perips:gpio: increase to 16 gpios

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-09-10 09:51:08 +08:00
parent 4086a2d863
commit 55f37e93fa
5 changed files with 181 additions and 148 deletions

View File

@ -8,28 +8,33 @@
],
regwidth: "32",
registers: [
{ name: "MODE",
desc: "gpio mode register",
{ name: "IO_MODE",
desc: "gpio input/output mode register",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "15:0",
name: "GPIO",
{ bits: "31:0",
desc: "gpio input or output mode, 2 bits for each gpio",
}
]
}
{ name: "INTR",
desc: "gpio interrupt register",
{ name: "INT_MODE",
desc: "gpio interrupt mode register",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "31:0",
desc: "gpio interrupt mode, 2 bits for each gpio",
}
]
}
{ name: "INT_PENDING",
desc: "gpio interrupt pending register",
swaccess: "rw",
hwaccess: "hrw",
fields: [
{ bits: "15:0",
name: "GPIO_INT",
desc: "gpio interrupt mode, 2 bits for each gpio",
}
{ bits: "23:16",
name: "GPIO_PENDING",
name: "GPIO_INT_PENDING",
swaccess: "rw1c",
desc: "gpio interrupt pending, 1 bits for each gpio",
}
@ -40,8 +45,7 @@
swaccess: "rw",
hwaccess: "hrw",
fields: [
{ bits: "7:0",
name: "GPIO",
{ bits: "15:0",
desc: "gpio input or output data, 1 bits for each gpio",
}
]
@ -51,8 +55,7 @@
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "7:0",
name: "GPIO",
{ bits: "15:0",
desc: "gpio input filter enable, 1 bits for each gpio",
}
]

View File

@ -14,7 +14,7 @@
limitations under the License.
*/
// 目前最多支持8个GPIO
// 目前最多支持16个GPIO
module gpio_core #(
parameter int GPIO_NUM = 2
)(
@ -28,6 +28,10 @@ module gpio_core #(
output logic irq_gpio1_o,
output logic irq_gpio2_4_o,
output logic irq_gpio5_7_o,
output logic irq_gpio8_o,
output logic irq_gpio9_o,
output logic irq_gpio10_12_o,
output logic irq_gpio13_15_o,
input logic reg_we_i,
input logic reg_re_i,
@ -37,10 +41,12 @@ module gpio_core #(
output logic [31:0] reg_rdata_o
);
localparam logic [1:0] INTR_MODE_NONE = 2'd0;
localparam logic [1:0] INTR_MODE_RAISE_EDGE = 2'd1;
localparam logic [1:0] INTR_MODE_FALL_EDGE = 2'd2;
localparam logic [1:0] INTR_MODE_DOUBLE_EDGE = 2'd3;
localparam logic [1:0] GPIO_MODE_NONE = 2'd0;
localparam logic [1:0] GPIO_MODE_INPUT = 2'd1;
localparam logic [1:0] GPIO_MODE_OUTPUT = 2'd2;
@ -65,7 +71,7 @@ module gpio_core #(
// 输出使能
for (genvar i = 0; i < GPIO_NUM; i = i + 1) begin : g_gpio_oe
assign gpio_oe[i] = reg2hw.mode.q[i*2+1:i*2] == GPIO_MODE_OUTPUT;
assign gpio_oe[i] = reg2hw.io_mode.q[i*2+1:i*2] == GPIO_MODE_OUTPUT;
end
assign gpio_oe_o = gpio_oe;
@ -79,7 +85,7 @@ module gpio_core #(
// 输入使能
for (genvar i = 0; i < GPIO_NUM; i = i + 1) begin : g_gpio_ie
assign gpio_ie[i] = reg2hw.mode.q[i*2+1:i*2] == GPIO_MODE_INPUT;
assign gpio_ie[i] = reg2hw.io_mode.q[i*2+1:i*2] == GPIO_MODE_INPUT;
end
// 硬件写data数据
@ -91,30 +97,42 @@ module gpio_core #(
// 中断有效
for (genvar i = 0; i < GPIO_NUM; i = i + 1) begin : g_gpio_intr_trigge
assign gpio_intr_trigge[i] = ((reg2hw.intr.gpio_int[i*2+1:i*2] == INTR_MODE_RAISE_EDGE) & gpio_raise_detect[i]) |
((reg2hw.intr.gpio_int[i*2+1:i*2] == INTR_MODE_FALL_EDGE) & gpio_fall_detect[i]) |
((reg2hw.intr.gpio_int[i*2+1:i*2] == INTR_MODE_DOUBLE_EDGE) & (gpio_raise_detect[i] | gpio_fall_detect[i]));
assign gpio_intr_trigge[i] = ((reg2hw.int_mode.q[i*2+1:i*2] == INTR_MODE_RAISE_EDGE) & gpio_raise_detect[i]) |
((reg2hw.int_mode.q[i*2+1:i*2] == INTR_MODE_FALL_EDGE) & gpio_fall_detect[i]) |
((reg2hw.int_mode.q[i*2+1:i*2] == INTR_MODE_DOUBLE_EDGE) & (gpio_raise_detect[i] | gpio_fall_detect[i]));
end
// 硬件写中断pending数据
for (genvar i = 0; i < GPIO_NUM; i = i + 1) begin : g_gpio_intr_pending
assign hw2reg.intr.gpio_pending.d[i] = gpio_intr_trigge[i] ? 1'b1 : reg2hw.intr.gpio_pending.q[i];
assign hw2reg.int_pending.d[i] = gpio_intr_trigge[i] ? 1'b1 : reg2hw.int_pending.q[i];
end
// 硬件写中断pending使能
assign hw2reg.intr.gpio_pending.de = |gpio_intr_trigge;
assign hw2reg.int_pending.de = |gpio_intr_trigge;
// 中断输出信号
if (GPIO_NUM >= 1) begin : g_num_ge_1
assign irq_gpio0_o = reg2hw.intr.gpio_pending.q[0];
assign irq_gpio0_o = reg2hw.int_pending.q[0];
end
if (GPIO_NUM >= 2) begin : g_num_ge_2
assign irq_gpio1_o = reg2hw.intr.gpio_pending.q[1];
assign irq_gpio1_o = reg2hw.int_pending.q[1];
end
if (GPIO_NUM >= 5) begin : g_num_ge_5
assign irq_gpio2_4_o = reg2hw.intr.gpio_pending.q[2] | reg2hw.intr.gpio_pending.q[3] | reg2hw.intr.gpio_pending.q[4];
assign irq_gpio2_4_o = reg2hw.int_pending.q[2] | reg2hw.int_pending.q[3] | reg2hw.int_pending.q[4];
end
if (GPIO_NUM >= 8) begin : g_num_ge_8
assign irq_gpio5_7_o = reg2hw.intr.gpio_pending.q[5] | reg2hw.intr.gpio_pending.q[6] | reg2hw.intr.gpio_pending.q[7];
assign irq_gpio5_7_o = reg2hw.int_pending.q[5] | reg2hw.int_pending.q[6] | reg2hw.int_pending.q[7];
end
if (GPIO_NUM >= 9) begin : g_num_ge_9
assign irq_gpio8_o = reg2hw.int_pending.q[8];
end
if (GPIO_NUM >= 10) begin : g_num_ge_10
assign irq_gpio9_o = reg2hw.int_pending.q[9];
end
if (GPIO_NUM >= 13) begin : g_num_ge_13
assign irq_gpio10_12_o = reg2hw.int_pending.q[10] | reg2hw.int_pending.q[11] | reg2hw.int_pending.q[12];
end
if (GPIO_NUM >= 16) begin : g_num_ge_16
assign irq_gpio13_15_o = reg2hw.int_pending.q[13] | reg2hw.int_pending.q[14] | reg2hw.int_pending.q[15];
end
// 沿检测

View File

@ -7,83 +7,80 @@
package gpio_reg_pkg;
// Address widths within the block
parameter int BlockAw = 4;
parameter int BlockAw = 5;
////////////////////////////
// Typedefs for registers //
////////////////////////////
typedef struct packed {
logic [31:0] q;
} gpio_reg2hw_io_mode_reg_t;
typedef struct packed {
logic [31:0] q;
} gpio_reg2hw_int_mode_reg_t;
typedef struct packed {
logic [15:0] q;
} gpio_reg2hw_mode_reg_t;
} gpio_reg2hw_int_pending_reg_t;
typedef struct packed {
struct packed {
logic [15:0] q;
} gpio_int;
struct packed {
logic [7:0] q;
} gpio_pending;
} gpio_reg2hw_intr_reg_t;
typedef struct packed {
logic [7:0] q;
logic [15:0] q;
} gpio_reg2hw_data_reg_t;
typedef struct packed {
logic [7:0] q;
logic [15:0] q;
} gpio_reg2hw_filter_reg_t;
typedef struct packed {
struct packed {
logic [15:0] d;
logic de;
} gpio_int;
struct packed {
logic [7:0] d;
logic de;
} gpio_pending;
} gpio_hw2reg_intr_reg_t;
logic [15:0] d;
logic de;
} gpio_hw2reg_int_pending_reg_t;
typedef struct packed {
logic [7:0] d;
logic [15:0] d;
logic de;
} gpio_hw2reg_data_reg_t;
// Register -> HW type
typedef struct packed {
gpio_reg2hw_mode_reg_t mode; // [55:40]
gpio_reg2hw_intr_reg_t intr; // [39:16]
gpio_reg2hw_data_reg_t data; // [15:8]
gpio_reg2hw_filter_reg_t filter; // [7:0]
gpio_reg2hw_io_mode_reg_t io_mode; // [111:80]
gpio_reg2hw_int_mode_reg_t int_mode; // [79:48]
gpio_reg2hw_int_pending_reg_t int_pending; // [47:32]
gpio_reg2hw_data_reg_t data; // [31:16]
gpio_reg2hw_filter_reg_t filter; // [15:0]
} gpio_reg2hw_t;
// HW -> register type
typedef struct packed {
gpio_hw2reg_intr_reg_t intr; // [34:9]
gpio_hw2reg_data_reg_t data; // [8:0]
gpio_hw2reg_int_pending_reg_t int_pending; // [33:17]
gpio_hw2reg_data_reg_t data; // [16:0]
} gpio_hw2reg_t;
// Register offsets
parameter logic [BlockAw-1:0] GPIO_MODE_OFFSET = 4'h0;
parameter logic [BlockAw-1:0] GPIO_INTR_OFFSET = 4'h4;
parameter logic [BlockAw-1:0] GPIO_DATA_OFFSET = 4'h8;
parameter logic [BlockAw-1:0] GPIO_FILTER_OFFSET = 4'hc;
parameter logic [BlockAw-1:0] GPIO_IO_MODE_OFFSET = 5'h0;
parameter logic [BlockAw-1:0] GPIO_INT_MODE_OFFSET = 5'h4;
parameter logic [BlockAw-1:0] GPIO_INT_PENDING_OFFSET = 5'h8;
parameter logic [BlockAw-1:0] GPIO_DATA_OFFSET = 5'hc;
parameter logic [BlockAw-1:0] GPIO_FILTER_OFFSET = 5'h10;
// Register index
typedef enum int {
GPIO_MODE,
GPIO_INTR,
GPIO_IO_MODE,
GPIO_INT_MODE,
GPIO_INT_PENDING,
GPIO_DATA,
GPIO_FILTER
} gpio_id_e;
// Register width information to check illegal writes
parameter logic [3:0] GPIO_PERMIT [4] = '{
4'b0011, // index[0] GPIO_MODE
4'b0111, // index[1] GPIO_INTR
4'b0001, // index[2] GPIO_DATA
4'b0001 // index[3] GPIO_FILTER
parameter logic [3:0] GPIO_PERMIT [5] = '{
4'b1111, // index[0] GPIO_IO_MODE
4'b1111, // index[1] GPIO_INT_MODE
4'b0011, // index[2] GPIO_INT_PENDING
4'b0011, // index[3] GPIO_DATA
4'b0011 // index[4] GPIO_FILTER
};
endpackage

View File

@ -23,7 +23,7 @@ module gpio_reg_top (
import gpio_reg_pkg::* ;
localparam int AW = 4;
localparam int AW = 5;
localparam int DW = 32;
localparam int DBW = DW/8; // Byte Width
@ -38,35 +38,36 @@ module gpio_reg_top (
// Define SW related signals
// Format: <reg>_<field>_{wd|we|qs}
// or <reg>_{wd|we|qs} if field == 1 or 0
logic mode_we;
logic [15:0] mode_qs;
logic [15:0] mode_wd;
logic intr_we;
logic [15:0] intr_gpio_int_qs;
logic [15:0] intr_gpio_int_wd;
logic [7:0] intr_gpio_pending_qs;
logic [7:0] intr_gpio_pending_wd;
logic io_mode_we;
logic [31:0] io_mode_qs;
logic [31:0] io_mode_wd;
logic int_mode_we;
logic [31:0] int_mode_qs;
logic [31:0] int_mode_wd;
logic int_pending_we;
logic [15:0] int_pending_qs;
logic [15:0] int_pending_wd;
logic data_we;
logic [7:0] data_qs;
logic [7:0] data_wd;
logic [15:0] data_qs;
logic [15:0] data_wd;
logic filter_we;
logic [7:0] filter_qs;
logic [7:0] filter_wd;
logic [15:0] filter_qs;
logic [15:0] filter_wd;
// Register instances
// R[mode]: V(False)
// R[io_mode]: V(False)
prim_subreg #(
.DW (16),
.DW (32),
.SWACCESS("RW"),
.RESVAL (16'h0)
) u_mode (
.RESVAL (32'h0)
) u_io_mode (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (mode_we),
.wd (mode_wd),
.we (io_mode_we),
.wd (io_mode_wd),
// from internal hardware
.de (1'b0),
@ -74,73 +75,73 @@ module gpio_reg_top (
// to internal hardware
.qe (),
.q (reg2hw.mode.q),
.q (reg2hw.io_mode.q),
// to register interface (read)
.qs (mode_qs)
.qs (io_mode_qs)
);
// R[intr]: V(False)
// R[int_mode]: V(False)
prim_subreg #(
.DW (32),
.SWACCESS("RW"),
.RESVAL (32'h0)
) u_int_mode (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (int_mode_we),
.wd (int_mode_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.int_mode.q),
// to register interface (read)
.qs (int_mode_qs)
);
// R[int_pending]: V(False)
// F[gpio_int]: 15:0
prim_subreg #(
.DW (16),
.SWACCESS("RW"),
.RESVAL (16'h0)
) u_intr_gpio_int (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (intr_we),
.wd (intr_gpio_int_wd),
// from internal hardware
.de (hw2reg.intr.gpio_int.de),
.d (hw2reg.intr.gpio_int.d),
// to internal hardware
.qe (),
.q (reg2hw.intr.gpio_int.q),
// to register interface (read)
.qs (intr_gpio_int_qs)
);
// F[gpio_pending]: 23:16
prim_subreg #(
.DW (8),
.SWACCESS("W1C"),
.RESVAL (8'h0)
) u_intr_gpio_pending (
.RESVAL (16'h0)
) u_int_pending (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (intr_we),
.wd (intr_gpio_pending_wd),
.we (int_pending_we),
.wd (int_pending_wd),
// from internal hardware
.de (hw2reg.intr.gpio_pending.de),
.d (hw2reg.intr.gpio_pending.d),
.de (hw2reg.int_pending.de),
.d (hw2reg.int_pending.d),
// to internal hardware
.qe (),
.q (reg2hw.intr.gpio_pending.q),
.q (reg2hw.int_pending.q),
// to register interface (read)
.qs (intr_gpio_pending_qs)
.qs (int_pending_qs)
);
// R[data]: V(False)
prim_subreg #(
.DW (8),
.DW (16),
.SWACCESS("RW"),
.RESVAL (8'h0)
.RESVAL (16'h0)
) u_data (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -165,9 +166,9 @@ module gpio_reg_top (
// R[filter]: V(False)
prim_subreg #(
.DW (8),
.DW (16),
.SWACCESS("RW"),
.RESVAL (8'h0)
.RESVAL (16'h0)
) u_filter (
.clk_i (clk_i),
.rst_ni (rst_ni),
@ -189,13 +190,14 @@ module gpio_reg_top (
);
logic [3:0] addr_hit;
logic [4:0] addr_hit;
always_comb begin
addr_hit = '0;
addr_hit[0] = (reg_addr == GPIO_MODE_OFFSET);
addr_hit[1] = (reg_addr == GPIO_INTR_OFFSET);
addr_hit[2] = (reg_addr == GPIO_DATA_OFFSET);
addr_hit[3] = (reg_addr == GPIO_FILTER_OFFSET);
addr_hit[0] = (reg_addr == GPIO_IO_MODE_OFFSET);
addr_hit[1] = (reg_addr == GPIO_INT_MODE_OFFSET);
addr_hit[2] = (reg_addr == GPIO_INT_PENDING_OFFSET);
addr_hit[3] = (reg_addr == GPIO_DATA_OFFSET);
addr_hit[4] = (reg_addr == GPIO_FILTER_OFFSET);
end
assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
@ -206,43 +208,48 @@ module gpio_reg_top (
((addr_hit[0] & (|(GPIO_PERMIT[0] & ~reg_be))) |
(addr_hit[1] & (|(GPIO_PERMIT[1] & ~reg_be))) |
(addr_hit[2] & (|(GPIO_PERMIT[2] & ~reg_be))) |
(addr_hit[3] & (|(GPIO_PERMIT[3] & ~reg_be)))));
(addr_hit[3] & (|(GPIO_PERMIT[3] & ~reg_be))) |
(addr_hit[4] & (|(GPIO_PERMIT[4] & ~reg_be)))));
end
assign mode_we = addr_hit[0] & reg_we & !reg_error;
assign io_mode_we = addr_hit[0] & reg_we & !reg_error;
assign mode_wd = reg_wdata[15:0];
assign intr_we = addr_hit[1] & reg_we & !reg_error;
assign io_mode_wd = reg_wdata[31:0];
assign int_mode_we = addr_hit[1] & reg_we & !reg_error;
assign intr_gpio_int_wd = reg_wdata[15:0];
assign int_mode_wd = reg_wdata[31:0];
assign int_pending_we = addr_hit[2] & reg_we & !reg_error;
assign intr_gpio_pending_wd = reg_wdata[23:16];
assign data_we = addr_hit[2] & reg_we & !reg_error;
assign int_pending_wd = reg_wdata[15:0];
assign data_we = addr_hit[3] & reg_we & !reg_error;
assign data_wd = reg_wdata[7:0];
assign filter_we = addr_hit[3] & reg_we & !reg_error;
assign data_wd = reg_wdata[15:0];
assign filter_we = addr_hit[4] & reg_we & !reg_error;
assign filter_wd = reg_wdata[7:0];
assign filter_wd = reg_wdata[15:0];
// Read data return
always_comb begin
reg_rdata_next = '0;
unique case (1'b1)
addr_hit[0]: begin
reg_rdata_next[15:0] = mode_qs;
reg_rdata_next[31:0] = io_mode_qs;
end
addr_hit[1]: begin
reg_rdata_next[15:0] = intr_gpio_int_qs;
reg_rdata_next[23:16] = intr_gpio_pending_qs;
reg_rdata_next[31:0] = int_mode_qs;
end
addr_hit[2]: begin
reg_rdata_next[7:0] = data_qs;
reg_rdata_next[15:0] = int_pending_qs;
end
addr_hit[3]: begin
reg_rdata_next[7:0] = filter_qs;
reg_rdata_next[15:0] = data_qs;
end
addr_hit[4]: begin
reg_rdata_next[15:0] = filter_qs;
end
default: begin

View File

@ -27,6 +27,10 @@ module gpio_top #(
output logic irq_gpio1_o,
output logic irq_gpio2_4_o,
output logic irq_gpio5_7_o,
output logic irq_gpio8_o,
output logic irq_gpio9_o,
output logic irq_gpio10_12_o,
output logic irq_gpio13_15_o,
// OBI总线接口信号
input logic req_i,
@ -75,6 +79,10 @@ module gpio_top #(
.irq_gpio1_o(irq_gpio1_o),
.irq_gpio2_4_o(irq_gpio2_4_o),
.irq_gpio5_7_o(irq_gpio5_7_o),
.irq_gpio8_o(irq_gpio8_o),
.irq_gpio9_o(irq_gpio9_o),
.irq_gpio10_12_o(irq_gpio10_12_o),
.irq_gpio13_15_o(irq_gpio13_15_o),
.reg_we_i (we),
.reg_re_i (re),
.reg_wdata_i(data_i),