rtl:perips: add pinmux

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-09-10 09:48:44 +08:00
parent 4d0f63ef86
commit 4086a2d863
6 changed files with 1501 additions and 0 deletions

View File

@ -65,6 +65,10 @@
../rtl/perips/spi/spi_top.sv
../rtl/perips/spi/spi_master.sv
../rtl/perips/spi/spi_transmit_byte.sv
../rtl/perips/pinmux/pinmux_reg_pkg.sv
../rtl/perips/pinmux/pinmux_reg_top.sv
../rtl/perips/pinmux/pinmux_core.sv
../rtl/perips/pinmux/pinmux_top.sv
../rtl/sys_bus/obi_interconnect.sv
../rtl/sys_bus/obi_interconnect_master_sel.sv

View File

@ -0,0 +1,83 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
{ name: "pinmux",
clocking: [{clock: "clk_i", reset: "rst_ni"}],
bus_interfaces: [
{ protocol: "tlul", direction: "device" }
],
regwidth: "32",
registers: [
{ name: "CTRL",
desc: "Pinmux control register",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "1:0",
name: "IO0_MUX",
desc: "IO0 mux",
}
{ bits: "3:2",
name: "IO1_MUX",
desc: "IO1 mux",
}
{ bits: "5:4",
name: "IO2_MUX",
desc: "IO2 mux",
}
{ bits: "7:6",
name: "IO3_MUX",
desc: "IO3 mux",
}
{ bits: "9:8",
name: "IO4_MUX",
desc: "IO4 mux",
}
{ bits: "11:10",
name: "IO5_MUX",
desc: "IO5 mux",
}
{ bits: "13:12",
name: "IO6_MUX",
desc: "IO6 mux",
}
{ bits: "15:14",
name: "IO7_MUX",
desc: "IO7 mux",
}
{ bits: "17:16",
name: "IO8_MUX",
desc: "IO8 mux",
}
{ bits: "19:18",
name: "IO9_MUX",
desc: "IO9 mux",
}
{ bits: "21:20",
name: "IO10_MUX",
desc: "IO10 mux",
}
{ bits: "23:22",
name: "IO11_MUX",
desc: "IO11 mux",
}
{ bits: "25:24",
name: "IO12_MUX",
desc: "IO12 mux",
}
{ bits: "27:26",
name: "IO13_MUX",
desc: "IO13 mux",
}
{ bits: "29:28",
name: "IO14_MUX",
desc: "IO14 mux",
}
{ bits: "31:30",
name: "IO15_MUX",
desc: "IO15 mux",
}
]
}
]
}

View File

@ -0,0 +1,613 @@
/*
Copyright 2021 Blue Liang, liangkangnan@163.com
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.
*/
module pinmux_core #(
parameter int GPIO_NUM = 16,
parameter int I2C_NUM = 2,
parameter int UART_NUM = 3,
parameter int SPI_NUM = 1
)(
input logic clk_i,
input logic rst_ni,
input logic [GPIO_NUM-1:0] gpio_oe_i,
input logic [GPIO_NUM-1:0] gpio_val_i,
output logic [GPIO_NUM-1:0] gpio_val_o,
input logic [I2C_NUM-1:0] i2c_sda_oe_i,
input logic [I2C_NUM-1:0] i2c_sda_val_i,
output logic [I2C_NUM-1:0] i2c_sda_val_o,
input logic [I2C_NUM-1:0] i2c_scl_oe_i,
input logic [I2C_NUM-1:0] i2c_scl_val_i,
output logic [I2C_NUM-1:0] i2c_scl_val_o,
input logic [UART_NUM-1:0] uart_tx_oe_i,
input logic [UART_NUM-1:0] uart_tx_val_i,
output logic [UART_NUM-1:0] uart_tx_val_o,
input logic [UART_NUM-1:0] uart_rx_oe_i,
input logic [UART_NUM-1:0] uart_rx_val_i,
output logic [UART_NUM-1:0] uart_rx_val_o,
input logic [SPI_NUM-1:0] spi_clk_oe_i,
input logic [SPI_NUM-1:0] spi_clk_val_i,
output logic [SPI_NUM-1:0] spi_clk_val_o,
input logic [SPI_NUM-1:0] spi_ss_oe_i,
input logic [SPI_NUM-1:0] spi_ss_val_i,
output logic [SPI_NUM-1:0] spi_ss_val_o,
input logic [ 3:0] spi_dq_oe_i [SPI_NUM-1:0],
input logic [ 3:0] spi_dq_val_i[SPI_NUM-1:0],
output logic [ 3:0] spi_dq_val_o[SPI_NUM-1:0],
input logic [GPIO_NUM-1:0] io_val_i,
output logic [GPIO_NUM-1:0] io_val_o,
output logic [GPIO_NUM-1:0] io_oe_o,
input logic reg_we_i,
input logic reg_re_i,
input logic [31:0] reg_wdata_i,
input logic [ 3:0] reg_be_i,
input logic [31:0] reg_addr_i,
output logic [31:0] reg_rdata_o
);
import pinmux_reg_pkg::*;
pinmux_reg_pkg::pinmux_reg2hw_t reg2hw;
logic [1:0] io0_mux;
logic [1:0] io1_mux;
logic [1:0] io2_mux;
logic [1:0] io3_mux;
logic [1:0] io4_mux;
logic [1:0] io5_mux;
logic [1:0] io6_mux;
logic [1:0] io7_mux;
logic [1:0] io8_mux;
logic [1:0] io9_mux;
logic [1:0] io10_mux;
logic [1:0] io11_mux;
logic [1:0] io12_mux;
logic [1:0] io13_mux;
logic [1:0] io14_mux;
logic [1:0] io15_mux;
assign io0_mux = reg2hw.ctrl.io0_mux.q;
assign io1_mux = reg2hw.ctrl.io1_mux.q;
assign io2_mux = reg2hw.ctrl.io2_mux.q;
assign io3_mux = reg2hw.ctrl.io3_mux.q;
assign io4_mux = reg2hw.ctrl.io4_mux.q;
assign io5_mux = reg2hw.ctrl.io5_mux.q;
assign io6_mux = reg2hw.ctrl.io6_mux.q;
assign io7_mux = reg2hw.ctrl.io7_mux.q;
assign io8_mux = reg2hw.ctrl.io8_mux.q;
assign io9_mux = reg2hw.ctrl.io9_mux.q;
assign io10_mux = reg2hw.ctrl.io10_mux.q;
assign io11_mux = reg2hw.ctrl.io11_mux.q;
assign io12_mux = reg2hw.ctrl.io12_mux.q;
assign io13_mux = reg2hw.ctrl.io13_mux.q;
assign io14_mux = reg2hw.ctrl.io14_mux.q;
assign io15_mux = reg2hw.ctrl.io15_mux.q;
// IO0
always_comb begin
io_val_o[0] = 1'b0;
io_oe_o[0] = 1'b0;
case (io0_mux)
// GPIO0
2'b00: begin
io_val_o[0] = gpio_val_i[0];
io_oe_o[0] = gpio_oe_i[0];
end
// UART0_TX
2'b01: begin
io_val_o[0] = uart_tx_val_i[0];
io_oe_o[0] = uart_tx_oe_i[0];
end
// UART0_RX
2'b10: begin
io_val_o[0] = uart_rx_val_i[0];
io_oe_o[0] = uart_rx_oe_i[0];
end
// GPIO0
2'b11: begin
io_val_o[0] = gpio_val_i[0];
io_oe_o[0] = gpio_oe_i[0];
end
default: ;
endcase
end
// IO1
always_comb begin
io_val_o[1] = 1'b0;
io_oe_o[1] = 1'b0;
case (io1_mux)
// GPIO1
2'b00: begin
io_val_o[1] = gpio_val_i[1];
io_oe_o[1] = gpio_oe_i[1];
end
// UART1_TX
2'b01: begin
io_val_o[1] = uart_tx_val_i[1];
io_oe_o[1] = uart_tx_oe_i[1];
end
// UART1_RX
2'b10: begin
io_val_o[1] = uart_rx_val_i[1];
io_oe_o[1] = uart_rx_oe_i[1];
end
// GPIO1
2'b11: begin
io_val_o[1] = gpio_val_i[1];
io_oe_o[1] = gpio_oe_i[1];
end
default: ;
endcase
end
// IO2
always_comb begin
io_val_o[2] = 1'b0;
io_oe_o[2] = 1'b0;
case (io2_mux)
// GPIO2
2'b00: begin
io_val_o[2] = gpio_val_i[2];
io_oe_o[2] = gpio_oe_i[2];
end
// UART2_TX
2'b01: begin
io_val_o[2] = uart_tx_val_i[2];
io_oe_o[2] = uart_tx_oe_i[2];
end
// UART2_RX
2'b10: begin
io_val_o[2] = uart_rx_val_i[2];
io_oe_o[2] = uart_rx_oe_i[2];
end
// GPIO2
2'b11: begin
io_val_o[2] = gpio_val_i[2];
io_oe_o[2] = gpio_oe_i[2];
end
default: ;
endcase
end
// IO3
always_comb begin
io_val_o[3] = 1'b0;
io_oe_o[3] = 1'b0;
case (io3_mux)
// GPIO3
2'b00: begin
io_val_o[3] = gpio_val_i[3];
io_oe_o[3] = gpio_oe_i[3];
end
// UART0_TX
2'b01: begin
io_val_o[3] = uart_tx_val_i[0];
io_oe_o[3] = uart_tx_oe_i[0];
end
// UART0_RX
2'b10: begin
io_val_o[3] = uart_rx_val_i[0];
io_oe_o[3] = uart_rx_oe_i[0];
end
// GPIO3
2'b11: begin
io_val_o[3] = gpio_val_i[3];
io_oe_o[3] = gpio_oe_i[3];
end
default: ;
endcase
end
// IO4
always_comb begin
io_val_o[4] = 1'b0;
io_oe_o[4] = 1'b0;
case (io4_mux)
// GPIO4
2'b00: begin
io_val_o[4] = gpio_val_i[4];
io_oe_o[4] = gpio_oe_i[4];
end
// UART1_TX
2'b01: begin
io_val_o[4] = uart_tx_val_i[1];
io_oe_o[4] = uart_tx_oe_i[1];
end
// UART1_RX
2'b10: begin
io_val_o[4] = uart_rx_val_i[1];
io_oe_o[4] = uart_rx_oe_i[1];
end
// GPIO4
2'b11: begin
io_val_o[4] = gpio_val_i[4];
io_oe_o[4] = gpio_oe_i[4];
end
default: ;
endcase
end
// IO5
always_comb begin
io_val_o[5] = 1'b0;
io_oe_o[5] = 1'b0;
case (io5_mux)
// GPIO5
2'b00: begin
io_val_o[5] = gpio_val_i[5];
io_oe_o[5] = gpio_oe_i[5];
end
// UART2_TX
2'b01: begin
io_val_o[5] = uart_tx_val_i[2];
io_oe_o[5] = uart_tx_oe_i[2];
end
// UART2_RX
2'b10: begin
io_val_o[5] = uart_rx_val_i[2];
io_oe_o[5] = uart_rx_oe_i[2];
end
// GPIO5
2'b11: begin
io_val_o[5] = gpio_val_i[5];
io_oe_o[5] = gpio_oe_i[5];
end
default: ;
endcase
end
// IO6
always_comb begin
io_val_o[6] = 1'b0;
io_oe_o[6] = 1'b0;
case (io6_mux)
// GPIO6
2'b00: begin
io_val_o[6] = gpio_val_i[6];
io_oe_o[6] = gpio_oe_i[6];
end
// I2C0_SCL
2'b01: begin
io_val_o[6] = i2c_scl_val_i[0];
io_oe_o[6] = i2c_scl_oe_i[0];
end
// I2C0_SDA
2'b10: begin
io_val_o[6] = i2c_sda_val_i[0];
io_oe_o[6] = i2c_sda_oe_i[0];
end
// GPIO6
2'b11: begin
io_val_o[6] = gpio_val_i[6];
io_oe_o[6] = gpio_oe_i[6];
end
default: ;
endcase
end
// IO7
always_comb begin
io_val_o[7] = 1'b0;
io_oe_o[7] = 1'b0;
case (io7_mux)
// GPIO7
2'b00: begin
io_val_o[7] = gpio_val_i[7];
io_oe_o[7] = gpio_oe_i[7];
end
// I2C1_SCL
2'b01: begin
io_val_o[7] = i2c_scl_val_i[1];
io_oe_o[7] = i2c_scl_oe_i[1];
end
// I2C1_SDA
2'b10: begin
io_val_o[7] = i2c_sda_val_i[1];
io_oe_o[7] = i2c_sda_oe_i[1];
end
// GPIO7
2'b11: begin
io_val_o[7] = gpio_val_i[7];
io_oe_o[7] = gpio_oe_i[7];
end
default: ;
endcase
end
// IO8
always_comb begin
io_val_o[8] = 1'b0;
io_oe_o[8] = 1'b0;
case (io8_mux)
// GPIO8
2'b00: begin
io_val_o[8] = gpio_val_i[8];
io_oe_o[8] = gpio_oe_i[8];
end
// I2C0_SCL
2'b01: begin
io_val_o[8] = i2c_scl_val_i[0];
io_oe_o[8] = i2c_scl_oe_i[0];
end
// I2C0_SDA
2'b10: begin
io_val_o[8] = i2c_sda_val_i[0];
io_oe_o[8] = i2c_sda_oe_i[0];
end
// GPIO8
2'b11: begin
io_val_o[8] = gpio_val_i[8];
io_oe_o[8] = gpio_oe_i[8];
end
default: ;
endcase
end
// IO9
always_comb begin
io_val_o[9] = 1'b0;
io_oe_o[9] = 1'b0;
case (io9_mux)
// GPIO9
2'b00: begin
io_val_o[9] = gpio_val_i[9];
io_oe_o[9] = gpio_oe_i[9];
end
// I2C1_SCL
2'b01: begin
io_val_o[9] = i2c_scl_val_i[1];
io_oe_o[9] = i2c_scl_oe_i[1];
end
// I2C1_SDA
2'b10: begin
io_val_o[9] = i2c_sda_val_i[1];
io_oe_o[9] = i2c_sda_oe_i[1];
end
// GPIO9
2'b11: begin
io_val_o[9] = gpio_val_i[9];
io_oe_o[9] = gpio_oe_i[9];
end
default: ;
endcase
end
// IO10
always_comb begin
io_val_o[10] = 1'b0;
io_oe_o[10] = 1'b0;
case (io10_mux)
// GPIO10
2'b00: begin
io_val_o[10] = gpio_val_i[10];
io_oe_o[10] = gpio_oe_i[10];
end
// SPI_CLK
2'b01: begin
io_val_o[10] = spi_clk_val_i[0];
io_oe_o[10] = spi_clk_oe_i[0];
end
default: begin
io_val_o[10] = gpio_val_i[10];
io_oe_o[10] = gpio_oe_i[10];
end
endcase
end
// IO11
always_comb begin
io_val_o[11] = 1'b0;
io_oe_o[11] = 1'b0;
case (io11_mux)
// GPIO11
2'b00: begin
io_val_o[11] = gpio_val_i[11];
io_oe_o[11] = gpio_oe_i[11];
end
// SPI_SS
2'b01: begin
io_val_o[11] = spi_ss_val_i[0];
io_oe_o[11] = spi_ss_oe_i[0];
end
default: begin
io_val_o[11] = gpio_val_i[11];
io_oe_o[11] = gpio_oe_i[11];
end
endcase
end
// IO12
always_comb begin
io_val_o[12] = 1'b0;
io_oe_o[12] = 1'b0;
case (io12_mux)
// GPIO12
2'b00: begin
io_val_o[12] = gpio_val_i[12];
io_oe_o[12] = gpio_oe_i[12];
end
// SPI_DQ0
2'b01: begin
io_val_o[12] = spi_dq_val_i[0][0];
io_oe_o[12] = spi_dq_oe_i[0][0];
end
default: begin
io_val_o[12] = gpio_val_i[12];
io_oe_o[12] = gpio_oe_i[12];
end
endcase
end
// IO13
always_comb begin
io_val_o[13] = 1'b0;
io_oe_o[13] = 1'b0;
case (io13_mux)
// GPIO13
2'b00: begin
io_val_o[13] = gpio_val_i[13];
io_oe_o[13] = gpio_oe_i[13];
end
// SPI_DQ1
2'b01: begin
io_val_o[13] = spi_dq_val_i[0][1];
io_oe_o[13] = spi_dq_oe_i[0][1];
end
default: begin
io_val_o[13] = gpio_val_i[13];
io_oe_o[13] = gpio_oe_i[13];
end
endcase
end
// IO14
always_comb begin
io_val_o[14] = 1'b0;
io_oe_o[14] = 1'b0;
case (io14_mux)
// GPIO14
2'b00: begin
io_val_o[14] = gpio_val_i[14];
io_oe_o[14] = gpio_oe_i[14];
end
// SPI_DQ2
2'b01: begin
io_val_o[14] = spi_dq_val_i[0][2];
io_oe_o[14] = spi_dq_oe_i[0][2];
end
default: begin
io_val_o[14] = gpio_val_i[14];
io_oe_o[14] = gpio_oe_i[14];
end
endcase
end
// IO15
always_comb begin
io_val_o[15] = 1'b0;
io_oe_o[15] = 1'b0;
case (io15_mux)
// GPIO15
2'b00: begin
io_val_o[15] = gpio_val_i[15];
io_oe_o[15] = gpio_oe_i[15];
end
// SPI_DQ3
2'b01: begin
io_val_o[15] = spi_dq_val_i[0][3];
io_oe_o[15] = spi_dq_oe_i[0][3];
end
default: begin
io_val_o[15] = gpio_val_i[15];
io_oe_o[15] = gpio_oe_i[15];
end
endcase
end
///////////////////////////////////////////////////////////////////////////////////////////
assign gpio_val_o[ 0] = ( io0_mux == 2'b00) ? io_val_i[ 0] : 1'b0;
assign gpio_val_o[ 1] = ( io1_mux == 2'b00) ? io_val_i[ 1] : 1'b0;
assign gpio_val_o[ 2] = ( io2_mux == 2'b00) ? io_val_i[ 2] : 1'b0;
assign gpio_val_o[ 3] = ( io3_mux == 2'b00) ? io_val_i[ 3] : 1'b0;
assign gpio_val_o[ 4] = ( io4_mux == 2'b00) ? io_val_i[ 4] : 1'b0;
assign gpio_val_o[ 5] = ( io5_mux == 2'b00) ? io_val_i[ 5] : 1'b0;
assign gpio_val_o[ 6] = ( io6_mux == 2'b00) ? io_val_i[ 6] : 1'b0;
assign gpio_val_o[ 7] = ( io7_mux == 2'b00) ? io_val_i[ 7] : 1'b0;
assign gpio_val_o[ 8] = ( io8_mux == 2'b00) ? io_val_i[ 8] : 1'b0;
assign gpio_val_o[ 9] = ( io9_mux == 2'b00) ? io_val_i[ 9] : 1'b0;
assign gpio_val_o[10] = (io10_mux == 2'b00) ? io_val_i[10] : 1'b0;
assign gpio_val_o[11] = (io11_mux == 2'b00) ? io_val_i[11] : 1'b0;
assign gpio_val_o[12] = (io12_mux == 2'b00) ? io_val_i[12] : 1'b0;
assign gpio_val_o[13] = (io13_mux == 2'b00) ? io_val_i[13] : 1'b0;
assign gpio_val_o[14] = (io14_mux == 2'b00) ? io_val_i[14] : 1'b0;
assign gpio_val_o[15] = (io15_mux == 2'b00) ? io_val_i[15] : 1'b0;
assign uart_tx_val_o[0] = (io0_mux == 2'b01) ? io_val_i[0] :
(io3_mux == 2'b01) ? io_val_i[3] :
1'b0;
assign uart_rx_val_o[0] = (io0_mux == 2'b10) ? io_val_i[0] :
(io3_mux == 2'b10) ? io_val_i[3] :
1'b0;
assign uart_tx_val_o[1] = (io1_mux == 2'b01) ? io_val_i[1] :
(io4_mux == 2'b01) ? io_val_i[4] :
1'b0;
assign uart_rx_val_o[1] = (io1_mux == 2'b10) ? io_val_i[1] :
(io4_mux == 2'b10) ? io_val_i[4] :
1'b0;
assign uart_tx_val_o[2] = (io2_mux == 2'b01) ? io_val_i[2] :
(io5_mux == 2'b01) ? io_val_i[5] :
1'b0;
assign uart_rx_val_o[2] = (io2_mux == 2'b10) ? io_val_i[2] :
(io5_mux == 2'b10) ? io_val_i[5] :
1'b0;
assign i2c_scl_val_o[0] = (io6_mux == 2'b01) ? io_val_i[6] :
(io8_mux == 2'b01) ? io_val_i[8] :
1'b0;
assign i2c_sda_val_o[0] = (io6_mux == 2'b10) ? io_val_i[6] :
(io8_mux == 2'b10) ? io_val_i[8] :
1'b0;
assign i2c_scl_val_o[1] = (io7_mux == 2'b01) ? io_val_i[7] :
(io9_mux == 2'b01) ? io_val_i[9] :
1'b0;
assign i2c_sda_val_o[1] = (io7_mux == 2'b10) ? io_val_i[7] :
(io9_mux == 2'b10) ? io_val_i[9] :
1'b0;
assign spi_clk_val_o[0] = (io10_mux == 2'b01) ? io_val_i[10] : 1'b0;
assign spi_ss_val_o[0] = (io11_mux == 2'b01) ? io_val_i[11] : 1'b0;
assign spi_dq_val_o[0][0] = (io12_mux == 2'b01) ? io_val_i[12] : 1'b0;
assign spi_dq_val_o[0][1] = (io13_mux == 2'b01) ? io_val_i[13] : 1'b0;
assign spi_dq_val_o[0][2] = (io14_mux == 2'b01) ? io_val_i[14] : 1'b0;
assign spi_dq_val_o[0][3] = (io15_mux == 2'b01) ? io_val_i[15] : 1'b0;
pinmux_reg_top u_pinmux_reg_top (
.clk_i (clk_i),
.rst_ni (rst_ni),
.reg2hw (reg2hw),
.reg_we (reg_we_i),
.reg_re (reg_re_i),
.reg_wdata (reg_wdata_i),
.reg_be (reg_be_i),
.reg_addr (reg_addr_i),
.reg_rdata (reg_rdata_o)
);
endmodule

View File

@ -0,0 +1,86 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Register Package auto-generated by `reggen` containing data structure
package pinmux_reg_pkg;
// Address widths within the block
parameter int BlockAw = 2;
////////////////////////////
// Typedefs for registers //
////////////////////////////
typedef struct packed {
struct packed {
logic [1:0] q;
} io0_mux;
struct packed {
logic [1:0] q;
} io1_mux;
struct packed {
logic [1:0] q;
} io2_mux;
struct packed {
logic [1:0] q;
} io3_mux;
struct packed {
logic [1:0] q;
} io4_mux;
struct packed {
logic [1:0] q;
} io5_mux;
struct packed {
logic [1:0] q;
} io6_mux;
struct packed {
logic [1:0] q;
} io7_mux;
struct packed {
logic [1:0] q;
} io8_mux;
struct packed {
logic [1:0] q;
} io9_mux;
struct packed {
logic [1:0] q;
} io10_mux;
struct packed {
logic [1:0] q;
} io11_mux;
struct packed {
logic [1:0] q;
} io12_mux;
struct packed {
logic [1:0] q;
} io13_mux;
struct packed {
logic [1:0] q;
} io14_mux;
struct packed {
logic [1:0] q;
} io15_mux;
} pinmux_reg2hw_ctrl_reg_t;
// Register -> HW type
typedef struct packed {
pinmux_reg2hw_ctrl_reg_t ctrl; // [31:0]
} pinmux_reg2hw_t;
// Register offsets
parameter logic [BlockAw-1:0] PINMUX_CTRL_OFFSET = 2'h0;
// Register index
typedef enum int {
PINMUX_CTRL
} pinmux_id_e;
// Register width information to check illegal writes
parameter logic [3:0] PINMUX_PERMIT [1] = '{
4'b1111 // index[0] PINMUX_CTRL
};
endpackage

View File

@ -0,0 +1,579 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Register Top module auto-generated by `reggen`
module pinmux_reg_top (
input logic clk_i,
input logic rst_ni,
// To HW
output pinmux_reg_pkg::pinmux_reg2hw_t reg2hw, // Write
input logic reg_we,
input logic reg_re,
input logic [31:0] reg_wdata,
input logic [ 3:0] reg_be,
input logic [31:0] reg_addr,
output logic [31:0] reg_rdata
);
import pinmux_reg_pkg::* ;
localparam int AW = 2;
localparam int DW = 32;
localparam int DBW = DW/8; // Byte Width
logic reg_error;
logic addrmiss, wr_err;
logic [DW-1:0] reg_rdata_next;
assign reg_rdata = reg_rdata_next;
assign reg_error = wr_err;
// Define SW related signals
// Format: <reg>_<field>_{wd|we|qs}
// or <reg>_{wd|we|qs} if field == 1 or 0
logic ctrl_we;
logic [1:0] ctrl_io0_mux_qs;
logic [1:0] ctrl_io0_mux_wd;
logic [1:0] ctrl_io1_mux_qs;
logic [1:0] ctrl_io1_mux_wd;
logic [1:0] ctrl_io2_mux_qs;
logic [1:0] ctrl_io2_mux_wd;
logic [1:0] ctrl_io3_mux_qs;
logic [1:0] ctrl_io3_mux_wd;
logic [1:0] ctrl_io4_mux_qs;
logic [1:0] ctrl_io4_mux_wd;
logic [1:0] ctrl_io5_mux_qs;
logic [1:0] ctrl_io5_mux_wd;
logic [1:0] ctrl_io6_mux_qs;
logic [1:0] ctrl_io6_mux_wd;
logic [1:0] ctrl_io7_mux_qs;
logic [1:0] ctrl_io7_mux_wd;
logic [1:0] ctrl_io8_mux_qs;
logic [1:0] ctrl_io8_mux_wd;
logic [1:0] ctrl_io9_mux_qs;
logic [1:0] ctrl_io9_mux_wd;
logic [1:0] ctrl_io10_mux_qs;
logic [1:0] ctrl_io10_mux_wd;
logic [1:0] ctrl_io11_mux_qs;
logic [1:0] ctrl_io11_mux_wd;
logic [1:0] ctrl_io12_mux_qs;
logic [1:0] ctrl_io12_mux_wd;
logic [1:0] ctrl_io13_mux_qs;
logic [1:0] ctrl_io13_mux_wd;
logic [1:0] ctrl_io14_mux_qs;
logic [1:0] ctrl_io14_mux_wd;
logic [1:0] ctrl_io15_mux_qs;
logic [1:0] ctrl_io15_mux_wd;
// Register instances
// R[ctrl]: V(False)
// F[io0_mux]: 1:0
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io0_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io0_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io0_mux.q),
// to register interface (read)
.qs (ctrl_io0_mux_qs)
);
// F[io1_mux]: 3:2
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io1_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io1_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io1_mux.q),
// to register interface (read)
.qs (ctrl_io1_mux_qs)
);
// F[io2_mux]: 5:4
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io2_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io2_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io2_mux.q),
// to register interface (read)
.qs (ctrl_io2_mux_qs)
);
// F[io3_mux]: 7:6
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io3_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io3_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io3_mux.q),
// to register interface (read)
.qs (ctrl_io3_mux_qs)
);
// F[io4_mux]: 9:8
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io4_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io4_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io4_mux.q),
// to register interface (read)
.qs (ctrl_io4_mux_qs)
);
// F[io5_mux]: 11:10
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io5_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io5_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io5_mux.q),
// to register interface (read)
.qs (ctrl_io5_mux_qs)
);
// F[io6_mux]: 13:12
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io6_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io6_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io6_mux.q),
// to register interface (read)
.qs (ctrl_io6_mux_qs)
);
// F[io7_mux]: 15:14
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io7_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io7_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io7_mux.q),
// to register interface (read)
.qs (ctrl_io7_mux_qs)
);
// F[io8_mux]: 17:16
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io8_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io8_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io8_mux.q),
// to register interface (read)
.qs (ctrl_io8_mux_qs)
);
// F[io9_mux]: 19:18
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io9_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io9_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io9_mux.q),
// to register interface (read)
.qs (ctrl_io9_mux_qs)
);
// F[io10_mux]: 21:20
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io10_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io10_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io10_mux.q),
// to register interface (read)
.qs (ctrl_io10_mux_qs)
);
// F[io11_mux]: 23:22
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io11_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io11_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io11_mux.q),
// to register interface (read)
.qs (ctrl_io11_mux_qs)
);
// F[io12_mux]: 25:24
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io12_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io12_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io12_mux.q),
// to register interface (read)
.qs (ctrl_io12_mux_qs)
);
// F[io13_mux]: 27:26
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io13_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io13_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io13_mux.q),
// to register interface (read)
.qs (ctrl_io13_mux_qs)
);
// F[io14_mux]: 29:28
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io14_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io14_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io14_mux.q),
// to register interface (read)
.qs (ctrl_io14_mux_qs)
);
// F[io15_mux]: 31:30
prim_subreg #(
.DW (2),
.SWACCESS("RW"),
.RESVAL (2'h0)
) u_ctrl_io15_mux (
.clk_i (clk_i),
.rst_ni (rst_ni),
// from register interface
.we (ctrl_we),
.wd (ctrl_io15_mux_wd),
// from internal hardware
.de (1'b0),
.d ('0),
// to internal hardware
.qe (),
.q (reg2hw.ctrl.io15_mux.q),
// to register interface (read)
.qs (ctrl_io15_mux_qs)
);
logic [0:0] addr_hit;
always_comb begin
addr_hit = '0;
addr_hit[0] = (reg_addr == PINMUX_CTRL_OFFSET);
end
assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
// Check sub-word write is permitted
always_comb begin
wr_err = (reg_we &
((addr_hit[0] & (|(PINMUX_PERMIT[0] & ~reg_be)))));
end
assign ctrl_we = addr_hit[0] & reg_we & !reg_error;
assign ctrl_io0_mux_wd = reg_wdata[1:0];
assign ctrl_io1_mux_wd = reg_wdata[3:2];
assign ctrl_io2_mux_wd = reg_wdata[5:4];
assign ctrl_io3_mux_wd = reg_wdata[7:6];
assign ctrl_io4_mux_wd = reg_wdata[9:8];
assign ctrl_io5_mux_wd = reg_wdata[11:10];
assign ctrl_io6_mux_wd = reg_wdata[13:12];
assign ctrl_io7_mux_wd = reg_wdata[15:14];
assign ctrl_io8_mux_wd = reg_wdata[17:16];
assign ctrl_io9_mux_wd = reg_wdata[19:18];
assign ctrl_io10_mux_wd = reg_wdata[21:20];
assign ctrl_io11_mux_wd = reg_wdata[23:22];
assign ctrl_io12_mux_wd = reg_wdata[25:24];
assign ctrl_io13_mux_wd = reg_wdata[27:26];
assign ctrl_io14_mux_wd = reg_wdata[29:28];
assign ctrl_io15_mux_wd = reg_wdata[31:30];
// Read data return
always_comb begin
reg_rdata_next = '0;
unique case (1'b1)
addr_hit[0]: begin
reg_rdata_next[1:0] = ctrl_io0_mux_qs;
reg_rdata_next[3:2] = ctrl_io1_mux_qs;
reg_rdata_next[5:4] = ctrl_io2_mux_qs;
reg_rdata_next[7:6] = ctrl_io3_mux_qs;
reg_rdata_next[9:8] = ctrl_io4_mux_qs;
reg_rdata_next[11:10] = ctrl_io5_mux_qs;
reg_rdata_next[13:12] = ctrl_io6_mux_qs;
reg_rdata_next[15:14] = ctrl_io7_mux_qs;
reg_rdata_next[17:16] = ctrl_io8_mux_qs;
reg_rdata_next[19:18] = ctrl_io9_mux_qs;
reg_rdata_next[21:20] = ctrl_io10_mux_qs;
reg_rdata_next[23:22] = ctrl_io11_mux_qs;
reg_rdata_next[25:24] = ctrl_io12_mux_qs;
reg_rdata_next[27:26] = ctrl_io13_mux_qs;
reg_rdata_next[29:28] = ctrl_io14_mux_qs;
reg_rdata_next[31:30] = ctrl_io15_mux_qs;
end
default: begin
reg_rdata_next = '1;
end
endcase
end
// Unused signal tieoff
// wdata / byte enable are not always fully used
// add a blanket unused statement to handle lint waivers
logic unused_wdata;
logic unused_be;
assign unused_wdata = ^reg_wdata;
assign unused_be = ^reg_be;
endmodule

View File

@ -0,0 +1,136 @@
/*
Copyright 2021 Blue Liang, liangkangnan@163.com
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.
*/
module pinmux_top #(
parameter int GPIO_NUM = 16,
parameter int I2C_NUM = 2,
parameter int UART_NUM = 3,
parameter int SPI_NUM = 1
)(
input logic clk_i,
input logic rst_ni,
// 16路GPIO
input logic [GPIO_NUM-1:0] gpio_oe_i,
input logic [GPIO_NUM-1:0] gpio_val_i,
output logic [GPIO_NUM-1:0] gpio_val_o,
// 2路I2C
input logic [I2C_NUM-1:0] i2c_sda_oe_i,
input logic [I2C_NUM-1:0] i2c_sda_val_i,
output logic [I2C_NUM-1:0] i2c_sda_val_o,
input logic [I2C_NUM-1:0] i2c_scl_oe_i,
input logic [I2C_NUM-1:0] i2c_scl_val_i,
output logic [I2C_NUM-1:0] i2c_scl_val_o,
// 3路UART
input logic [UART_NUM-1:0] uart_tx_oe_i,
input logic [UART_NUM-1:0] uart_tx_val_i,
output logic [UART_NUM-1:0] uart_tx_val_o,
input logic [UART_NUM-1:0] uart_rx_oe_i,
input logic [UART_NUM-1:0] uart_rx_val_i,
output logic [UART_NUM-1:0] uart_rx_val_o,
// 1路SPI
input logic [SPI_NUM-1:0] spi_clk_oe_i,
input logic [SPI_NUM-1:0] spi_clk_val_i,
output logic [SPI_NUM-1:0] spi_clk_val_o,
input logic [SPI_NUM-1:0] spi_ss_oe_i,
input logic [SPI_NUM-1:0] spi_ss_val_i,
output logic [SPI_NUM-1:0] spi_ss_val_o,
input logic [ 3:0] spi_dq_oe_i [SPI_NUM-1:0],
input logic [ 3:0] spi_dq_val_i[SPI_NUM-1:0],
output logic [ 3:0] spi_dq_val_o[SPI_NUM-1:0],
input logic [GPIO_NUM-1:0] io_val_i,
output logic [GPIO_NUM-1:0] io_val_o,
output logic [GPIO_NUM-1:0] io_oe_o,
// OBI总线接口信号
input logic req_i,
input logic we_i,
input logic [ 3:0] be_i,
input logic [31:0] addr_i,
input logic [31:0] data_i,
output logic gnt_o,
output logic rvalid_o,
output logic [31:0] data_o
);
logic re;
logic we;
logic [31:0] addr;
logic [31:0] reg_rdata;
assign gnt_o = req_i;
// 读信号
assign re = req_i & (!we_i);
// 写信号
assign we = req_i & we_i;
// 去掉基地址
assign addr = {16'h0, addr_i[15:0]};
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvalid_o <= '0;
data_o <= '0;
end else begin
rvalid_o <= req_i;
data_o <= reg_rdata;
end
end
pinmux_core #(
.GPIO_NUM(GPIO_NUM),
.I2C_NUM(I2C_NUM),
.UART_NUM(UART_NUM),
.SPI_NUM(SPI_NUM)
) u_pinmux_core (
.clk_i (clk_i),
.rst_ni (rst_ni),
.gpio_oe_i,
.gpio_val_i,
.gpio_val_o,
.i2c_sda_oe_i,
.i2c_sda_val_i,
.i2c_sda_val_o,
.i2c_scl_oe_i,
.i2c_scl_val_i,
.i2c_scl_val_o,
.uart_tx_oe_i,
.uart_tx_val_i,
.uart_tx_val_o,
.uart_rx_oe_i,
.uart_rx_val_i,
.uart_rx_val_o,
.spi_clk_oe_i,
.spi_clk_val_i,
.spi_clk_val_o,
.spi_ss_oe_i,
.spi_ss_val_i,
.spi_ss_val_o,
.spi_dq_oe_i,
.spi_dq_val_i,
.spi_dq_val_o,
.io_val_i,
.io_val_o,
.io_oe_o,
.reg_we_i (we),
.reg_re_i (re),
.reg_wdata_i(data_i),
.reg_be_i (be_i),
.reg_addr_i (addr),
.reg_rdata_o(reg_rdata)
);
endmodule