diff --git a/rtl/perips/gpio/gpio.hjson b/rtl/perips/gpio/gpio.hjson index 5b6e947..1227025 100644 --- a/rtl/perips/gpio/gpio.hjson +++ b/rtl/perips/gpio/gpio.hjson @@ -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", } ] diff --git a/rtl/perips/gpio/gpio_core.sv b/rtl/perips/gpio/gpio_core.sv index 9f04985..30a911d 100644 --- a/rtl/perips/gpio/gpio_core.sv +++ b/rtl/perips/gpio/gpio_core.sv @@ -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 // 沿检测 diff --git a/rtl/perips/gpio/gpio_reg_pkg.sv b/rtl/perips/gpio/gpio_reg_pkg.sv index ea56835..022f1ad 100644 --- a/rtl/perips/gpio/gpio_reg_pkg.sv +++ b/rtl/perips/gpio/gpio_reg_pkg.sv @@ -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 diff --git a/rtl/perips/gpio/gpio_reg_top.sv b/rtl/perips/gpio/gpio_reg_top.sv index b385fcc..9186cf8 100644 --- a/rtl/perips/gpio/gpio_reg_top.sv +++ b/rtl/perips/gpio/gpio_reg_top.sv @@ -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: __{wd|we|qs} // or _{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 diff --git a/rtl/perips/gpio/gpio_top.sv b/rtl/perips/gpio/gpio_top.sv index ac5c8f4..d1e112d 100644 --- a/rtl/perips/gpio/gpio_top.sv +++ b/rtl/perips/gpio/gpio_top.sv @@ -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),