blob: 33f7d646a0a15d0485a3a050fa2f715f6f9fc864 [file] [log] [blame]
// Softshell Top.
//
// SPDX-FileCopyrightText: (c) 2020 Harrison Pham <harrison@harrisonpham.com>
// SPDX-License-Identifier: Apache-2.0
//
// 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.
// Pads:
// io[37:6] - Mapped to 32-bit pinmux (gpios, flexio, uart)
// io[8] - Flash CSB
// io[9] - Flash CLK
// io[10] - Flash DIO0
// io[11] - Flash DIO1
// io[12] - Flash DIO2
// io[13] - Flash DIO3
//
// LA:
// la_data_in[0] - Wishbone reset (also resets CPUs)
// la_data_in[1] - CPU0 reset
// la_data_in[2] - CPU1 reset
// la_data_in[3] - CPU2 reset
// la_data_in[4] - CPU3 reset
//
// la_data_out[31:0] - GPIO out
// la_data_out[63:32] - GPIO in
// `include "third_party/verilog-wishbone/rtl/wb_arbiter_5.v"
// `include "third_party/verilog-wishbone/rtl/arbiter.v"
// `include "third_party/verilog-wishbone/rtl/priority_encoder.v"
// `include "third_party/verilog-wishbone/rtl/wb_mux_3.v"
// `include "third_party/verilog-wishbone/rtl/wb_mux_4.v"
// `include "rv_core.v"
// `include "third_party/picorv32_wb/mem_ff_wb.v"
// `include "third_party/picorv32_wb/simpleuart.v"
// `include "third_party/picorv32_wb/spimemio.v"
// Total shared memory in 32-bit words.
`define SHARED_MEM_WORDS 512
// Number of CPU cores.
// TODO(hdpham): Make this less terrible and dangerous to use.
`define NUM_CPUS 3
`define HAS_CPU3
// `define HAS_CPU4
module softshell_top (
`ifdef USE_POWER_PINS
inout vdda1, // User area 1 3.3V supply
inout vdda2, // User area 2 3.3V supply
inout vssa1, // User area 1 analog ground
inout vssa2, // User area 2 analog ground
inout vccd1, // User area 1 1.8V supply
inout vccd2, // User area 2 1.8v supply
inout vssd1, // User area 1 digital ground
inout vssd2, // User area 2 digital ground
`endif
// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,
// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oen,
// IOs
input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb
);
// Softshell base address (used for filtering addresses from Caravel).
parameter SOFTSHELL_MASK = 32'hff00_0000;
parameter SOFTSHELL_ADDR = 32'h3000_0000;
// Slave base addresses.
parameter SHARED_RAM_MASK = 32'hfff0_0000;
parameter SHARED_RAM_ADDR = 32'h3000_0000;
parameter SHARED_FLASH_MASK = 32'hfff0_0000;
parameter SHARED_FLASH_ADDR = 32'h3040_0000;
parameter FLASH_CONFIG_MASK = 32'hffff_0000;
parameter FLASH_CONFIG_ADDR = 32'h3080_0000;
parameter PINMUX_ADDR_MASK = 32'hffff_0000;
parameter PINMUX_BASE_ADDR = 32'h3081_0000;
parameter UART0_ADDR_MASK = 32'hffff_0000;
parameter UART0_BASE_ADDR = 32'h3082_0000;
// wire clk;
// wire resetb;
// assign clk = wb_clk_i;
// assign resetb = ~wb_rst_i;
// // Use a GPIO as a clock source just in case clocking through the wrapper
// // isn't flexible enough. This is pretty nasty, but hopefully with enough
// // muxing options we'll be okay.
// // TODO(harrisonpham): Instantiate proper clock buffer / glitchless mux.
// wire clk_ext;
// reg clk_muxed;
// wire [1:0] clk_sel;
// reg clk_ext_div2;
// assign clk_sel = la_data_in[1:0];
// assign clk_ext = io_in[`MPRJ_IO_PADS-1];
// // Reset is not synchronized! Be careful when releasing reset
// // (do it after clock is stable).
// // TODO(harrisonpham): Synchronize reset to clk_muxed domain.
// wire resetb_muxed;
// assign resetb_muxed = resetb & la_data_in[2];
// always @(posedge clk_ext) begin
// if (!resetb) begin
// clk_ext_div2 <= 1'b0;
// end else begin
// clk_ext_div2 <= ~clk_ext_div2;
// end
// end
// always @* begin
// case (clk_sel)
// 2'b00: clk_muxed = clk;
// 2'b01: clk_muxed = clk_ext;
// 2'b10: clk_muxed = clk_ext_div2;
// 2'b11: clk_muxed = 1'b0;
// endcase
// end
// Async reset generator.
// Resets from either a wishbone reset or a logic analyzer reset request.
reg [2:0] reset_pipe;
wire reset_in;
wire reset;
assign reset_in = wb_rst_i | la_data_in[0];
assign reset = reset_pipe[2];
always @(posedge wb_clk_i or posedge reset_in) begin
if (reset_in) begin
reset_pipe <= 3'b111;
end else begin
reset_pipe <= {reset_pipe[1:0], 1'b0};
end
end
// CPU signals.
wire [31:0] wbm_adr_i [`NUM_CPUS-1:0];
wire [31:0] wbm_dat_i [`NUM_CPUS-1:0];
wire [31:0] wbm_dat_o [`NUM_CPUS-1:0];
wire wbm_we_i [`NUM_CPUS-1:0];
wire [3:0] wbm_sel_i [`NUM_CPUS-1:0];
wire wbm_stb_i [`NUM_CPUS-1:0];
wire wbm_ack_o [`NUM_CPUS-1:0];
wire wbm_err_o [`NUM_CPUS-1:0];
wire wbm_rty_o [`NUM_CPUS-1:0];
wire wbm_cyc_i [`NUM_CPUS-1:0];
wire [31:0] gpio_in [`NUM_CPUS-1:0];
wire [31:0] gpio_out [`NUM_CPUS-1:0];
wire [31:0] gpio_oeb [`NUM_CPUS-1:0];
wire [7:0] flexio_in [`NUM_CPUS-1:0];
wire [7:0] flexio_out [`NUM_CPUS-1:0];
wire [7:0] flexio_oeb [`NUM_CPUS-1:0];
wire cpu_reset[`NUM_CPUS-1:0];
// Generate the CPUs
genvar i;
generate
for (i = 0; i < `NUM_CPUS; i = i + 1) begin : cpus
assign cpu_reset[i] = la_data_in[i + 1];
rv_core #(
// TODO(hdpham): Resize this once the design fits.
.MEM_WORDS(32),
// Boot from flash.
// TODO(hdpham): Should we switch this back to RAM?
.PROGADDR_RESET(SHARED_FLASH_ADDR | ((i + 1) << 16)),
.CORE_ID(i)
) core (
.wb_clk_i(wb_clk_i),
.wb_rst_i(reset | cpu_reset[i]),
.shared_ack_i(wbm_ack_o[i]),
.shared_dat_i(wbm_dat_o[i]),
.shared_cyc_o(wbm_cyc_i[i]),
.shared_stb_o(wbm_stb_i[i]),
.shared_we_o(wbm_we_i[i]),
.shared_sel_o(wbm_sel_i[i]),
.shared_adr_o(wbm_adr_i[i]),
.shared_dat_o(wbm_dat_i[i]),
.gpio_in(gpio_in[i]),
.gpio_out(gpio_out[i]),
.gpio_oeb(gpio_oeb[i]),
.flexio_in(flexio_in[i]),
.flexio_out(flexio_out[i]),
.flexio_oeb(flexio_oeb[i])
);
end
endgenerate
// Shared memory.
wire [31:0] mem_adr_i;
wire [31:0] mem_dat_i;
wire [3:0] mem_sel_i;
wire mem_we_i;
wire mem_cyc_i;
wire mem_stb_i;
wire mem_ack_o;
wire [31:0] mem_dat_o;
mem_ff_wb #(
.MEM_WORDS(`SHARED_MEM_WORDS)
) shared_mem (
.wb_clk_i(wb_clk_i),
.wb_rst_i(reset),
.wb_adr_i(mem_adr_i),
.wb_dat_i(mem_dat_i),
.wb_sel_i(mem_sel_i),
.wb_we_i(mem_we_i),
.wb_cyc_i(mem_cyc_i),
.wb_stb_i(mem_stb_i),
.wb_ack_o(mem_ack_o),
.wb_dat_o(mem_dat_o)
);
// Pinmux.
wire [31:0] pinmux_adr_i;
wire [31:0] pinmux_dat_i;
wire [3:0] pinmux_sel_i;
wire pinmux_cyc_i;
wire pinmux_stb_i;
wire pinmux_we_i;
wire [31:0] pinmux_dat_o;
wire pinmux_ack_o;
wire [31:0] pinmux_gpio_in;
wire [31:0] pinmux_gpio_out;
wire [31:0] pinmux_gpio_oeb;
pinmux #(
.NUM_INPUTS(1),
.NUM_OUTPUTS(1 + `NUM_CPUS * 8),
.NUM_GPIOS(32)
) pinmux (
.wb_clk_i(wb_clk_i),
.wb_rst_i(reset),
.wb_adr_i(pinmux_adr_i),
.wb_dat_i(pinmux_dat_i),
.wb_sel_i(pinmux_sel_i),
.wb_cyc_i(pinmux_cyc_i),
.wb_stb_i(pinmux_stb_i),
.wb_we_i(pinmux_we_i),
.wb_dat_o(pinmux_dat_o),
.wb_ack_o(pinmux_ack_o),
.gpio_in(pinmux_gpio_in),
.gpio_out(pinmux_gpio_out),
.gpio_oeb(pinmux_gpio_oeb),
.peripheral_in({uart_rx}),
.peripheral_out({
`ifdef HAS_CPU4
flexio_out[3],
`endif
`ifdef HAS_CPU3
flexio_out[2],
`endif
flexio_out[1],
flexio_out[0],
uart_tx
}),
.peripheral_oeb({
`ifdef HAS_CPU4
flexio_oeb[3],
`endif
`ifdef HAS_CPU3
flexio_oeb[2],
`endif
flexio_oeb[1],
flexio_oeb[0],
1'b0
})
);
// Uarts.
wire [31:0] uart_adr_i;
wire [31:0] uart_dat_i;
wire [3:0] uart_sel_i;
wire uart_we_i;
wire uart_cyc_i;
wire uart_stb_i;
wire uart_ack_o;
wire [31:0] uart_dat_o;
wire uart_enabled;
wire uart_tx;
wire uart_rx;
simpleuart_wb #(
.BASE_ADR(UART0_BASE_ADDR)
) uart0 (
.wb_clk_i(wb_clk_i),
.wb_rst_i(reset),
.wb_adr_i(uart_adr_i),
.wb_dat_i(uart_dat_i),
.wb_sel_i(uart_sel_i),
.wb_we_i(uart_we_i),
.wb_cyc_i(uart_cyc_i),
.wb_stb_i(uart_stb_i),
.wb_ack_o(uart_ack_o),
.wb_dat_o(uart_dat_o),
.uart_enabled(uart_enabled),
.ser_tx(uart_tx),
.ser_rx(uart_rx)
);
// Flash.
wire [31:0] flash_adr_i;
wire [31:0] flash_dat_i;
wire [3:0] flash_sel_i;
wire flash_we_i;
wire flash_cyc_i;
wire flash_stb_i;
wire flash_ack_o;
wire [31:0] flash_dat_o;
wire flash_cfg_we_i;
wire flash_cfg_cyc_i;
wire flash_cfg_stb_i;
wire flash_cfg_ack_o;
wire [31:0] flash_cfg_dat_o;
wire flash_csb_oeb;
wire flash_clk_oeb;
wire flash_io0_oeb;
wire flash_io1_oeb;
wire flash_io2_oeb;
wire flash_io3_oeb;
wire flash_csb;
wire flash_clk;
wire flash_io0_do;
wire flash_io1_do;
wire flash_io2_do;
wire flash_io3_do;
wire flash_io0_di;
wire flash_io1_di;
wire flash_io2_di;
wire flash_io3_di;
// Mask off the unused upper flash address bits.
wire [31:0] flash_adr_i_masked;
assign flash_adr_i_masked = flash_adr_i & ~SHARED_FLASH_MASK;
spimemio_wb flash (
.wb_clk_i(wb_clk_i),
.wb_rst_i(reset),
.wb_adr_i(flash_adr_i_masked),
.wb_dat_i(flash_dat_i),
.wb_sel_i(flash_sel_i),
.wb_we_i(flash_we_i | flash_cfg_we_i),
.wb_cyc_i(flash_cyc_i | flash_cfg_cyc_i),
.wb_flash_stb_i(flash_stb_i),
.wb_cfg_stb_i(flash_cfg_stb_i),
.wb_flash_ack_o(flash_ack_o),
.wb_cfg_ack_o(flash_cfg_ack_o),
.wb_flash_dat_o(flash_dat_o),
.wb_cfg_dat_o(flash_cfg_dat_o),
.pass_thru(1'b0),
.pass_thru_csb(1'b0),
.pass_thru_sck(1'b0),
.pass_thru_sdi(1'b0),
.pass_thru_sdo(),
.flash_csb(flash_csb),
.flash_clk(flash_clk),
.flash_csb_oeb(flash_csb_oeb),
.flash_clk_oeb(flash_clk_oeb),
.flash_io0_oeb(flash_io0_oeb),
.flash_io1_oeb(flash_io1_oeb),
.flash_io2_oeb(flash_io2_oeb),
.flash_io3_oeb(flash_io3_oeb),
.flash_csb_ieb(),
.flash_clk_ieb(),
.flash_io0_ieb(),
.flash_io1_ieb(),
.flash_io2_ieb(),
.flash_io3_ieb(),
.flash_io0_do(flash_io0_do),
.flash_io1_do(flash_io1_do),
.flash_io2_do(flash_io2_do),
.flash_io3_do(flash_io3_do),
.flash_io0_di(flash_io0_di),
.flash_io1_di(flash_io1_di),
.flash_io2_di(flash_io2_di),
.flash_io3_di(flash_io3_di)
);
// Interconnect bus.
wire [31:0] mux_adr_i;
wire [31:0] mux_dat_i;
wire [3:0] mux_sel_i;
wire mux_we_i;
wire mux_cyc_i;
wire mux_stb_i;
wire mux_ack_o;
wire [31:0] mux_dat_o;
// Filter addresses from Caravel since we want to be absolutely sure it is
// selecting us before letting it access the arbiter. This is mostly needed
// because the wb_intercon.v implementation in Caravel doesn't corrently
// filter the wb_cyc_i signal to slaves.
wire wbs_addr_sel;
assign wbs_addr_sel = (wbs_adr_i & SOFTSHELL_MASK) == SOFTSHELL_ADDR;
// Round-robin arbiter for shared resources.
`ifdef HAS_CPU4
wb_arbiter_5 #(
`elsif HAS_CPU3
wb_arbiter_4 #(
`else
wb_arbiter_3 #(
`endif
.ARB_TYPE("ROUND_ROBIN")
) arbiter (
.clk(wb_clk_i),
.rst(reset),
.wbm0_adr_i(wbs_adr_i),
.wbm0_dat_i(wbs_dat_i),
.wbm0_dat_o(wbs_dat_o),
.wbm0_we_i(wbs_we_i & wbs_addr_sel),
.wbm0_sel_i(wbs_sel_i),
.wbm0_stb_i(wbs_stb_i & wbs_addr_sel),
.wbm0_ack_o(wbs_ack_o),
.wbm0_err_o(),
.wbm0_rty_o(),
.wbm0_cyc_i(wbs_cyc_i & wbs_addr_sel),
.wbm1_adr_i(wbm_adr_i[0]),
.wbm1_dat_i(wbm_dat_i[0]),
.wbm1_dat_o(wbm_dat_o[0]),
.wbm1_we_i(wbm_we_i[0]),
.wbm1_sel_i(wbm_sel_i[0]),
.wbm1_stb_i(wbm_stb_i[0]),
.wbm1_ack_o(wbm_ack_o[0]),
.wbm1_err_o(wbm_err_o[0]),
.wbm1_rty_o(wbm_rty_o[0]),
.wbm1_cyc_i(wbm_cyc_i[0]),
.wbm2_adr_i(wbm_adr_i[1]),
.wbm2_dat_i(wbm_dat_i[1]),
.wbm2_dat_o(wbm_dat_o[1]),
.wbm2_we_i(wbm_we_i[1]),
.wbm2_sel_i(wbm_sel_i[1]),
.wbm2_stb_i(wbm_stb_i[1]),
.wbm2_ack_o(wbm_ack_o[1]),
.wbm2_err_o(wbm_err_o[1]),
.wbm2_rty_o(wbm_rty_o[1]),
.wbm2_cyc_i(wbm_cyc_i[1]),
`ifdef HAS_CPU3
.wbm3_adr_i(wbm_adr_i[2]),
.wbm3_dat_i(wbm_dat_i[2]),
.wbm3_dat_o(wbm_dat_o[2]),
.wbm3_we_i(wbm_we_i[2]),
.wbm3_sel_i(wbm_sel_i[2]),
.wbm3_stb_i(wbm_stb_i[2]),
.wbm3_ack_o(wbm_ack_o[2]),
.wbm3_err_o(wbm_err_o[2]),
.wbm3_rty_o(wbm_rty_o[2]),
.wbm3_cyc_i(wbm_cyc_i[2]),
`endif
`ifdef HAS_CPU4
.wbm4_adr_i(wbm_adr_i[3]),
.wbm4_dat_i(wbm_dat_i[3]),
.wbm4_dat_o(wbm_dat_o[3]),
.wbm4_we_i(wbm_we_i[3]),
.wbm4_sel_i(wbm_sel_i[3]),
.wbm4_stb_i(wbm_stb_i[3]),
.wbm4_ack_o(wbm_ack_o[3]),
.wbm4_err_o(wbm_err_o[3]),
.wbm4_rty_o(wbm_rty_o[3]),
.wbm4_cyc_i(wbm_cyc_i[3]),
`endif
.wbs_adr_o(mux_adr_i),
.wbs_dat_i(mux_dat_o),
.wbs_dat_o(mux_dat_i),
.wbs_we_o(mux_we_i),
.wbs_sel_o(mux_sel_i),
.wbs_stb_o(mux_stb_i),
.wbs_ack_i(mux_ack_o),
.wbs_err_i(1'b0),
.wbs_rty_i(1'b0),
.wbs_cyc_o(mux_cyc_i)
);
// Wishbone slave mux for shared memory and peripherals.
wb_mux_5 interconnect (
.wbm_adr_i(mux_adr_i),
.wbm_dat_i(mux_dat_i),
.wbm_dat_o(mux_dat_o),
.wbm_we_i(mux_we_i),
.wbm_sel_i(mux_sel_i),
.wbm_stb_i(mux_stb_i),
.wbm_ack_o(mux_ack_o),
.wbm_err_o(),
.wbm_rty_o(),
.wbm_cyc_i(mux_cyc_i),
.wbs0_adr_o(mem_adr_i),
.wbs0_dat_i(mem_dat_o),
.wbs0_dat_o(mem_dat_i),
.wbs0_we_o(mem_we_i),
.wbs0_sel_o(mem_sel_i),
.wbs0_stb_o(mem_stb_i),
.wbs0_ack_i(mem_ack_o),
.wbs0_err_i(1'b0),
.wbs0_rty_i(1'b0),
.wbs0_cyc_o(mem_cyc_i),
.wbs0_addr(SHARED_RAM_ADDR),
.wbs0_addr_msk(SHARED_RAM_MASK),
.wbs1_adr_o(uart_adr_i),
.wbs1_dat_i(uart_dat_o),
.wbs1_dat_o(uart_dat_i),
.wbs1_we_o(uart_we_i),
.wbs1_sel_o(uart_sel_i),
.wbs1_stb_o(uart_stb_i),
.wbs1_ack_i(uart_ack_o),
.wbs1_err_i(1'b0),
.wbs1_rty_i(1'b0),
.wbs1_cyc_o(uart_cyc_i),
.wbs1_addr(UART0_BASE_ADDR),
.wbs1_addr_msk(UART0_ADDR_MASK),
.wbs2_adr_o(flash_adr_i),
.wbs2_dat_i(flash_dat_o),
.wbs2_dat_o(flash_dat_i),
.wbs2_we_o(flash_we_i),
.wbs2_sel_o(flash_sel_i),
.wbs2_stb_o(flash_stb_i),
.wbs2_ack_i(flash_ack_o),
.wbs2_err_i(1'b0),
.wbs2_rty_i(1'b0),
.wbs2_cyc_o(flash_cyc_i),
.wbs2_addr(SHARED_FLASH_ADDR),
.wbs2_addr_msk(SHARED_FLASH_MASK),
.wbs3_adr_o(),
.wbs3_dat_i(flash_cfg_dat_o),
.wbs3_dat_o(),
.wbs3_we_o(flash_cfg_we_i),
.wbs3_sel_o(),
.wbs3_stb_o(flash_cfg_stb_i),
.wbs3_ack_i(flash_cfg_ack_o),
.wbs3_err_i(1'b0),
.wbs3_rty_i(1'b0),
.wbs3_cyc_o(flash_cfg_cyc_i),
.wbs3_addr(FLASH_CONFIG_ADDR),
.wbs3_addr_msk(FLASH_CONFIG_MASK),
.wbs4_adr_o(pinmux_adr_i),
.wbs4_dat_i(pinmux_dat_o),
.wbs4_dat_o(pinmux_dat_i),
.wbs4_we_o(pinmux_we_i),
.wbs4_sel_o(pinmux_sel_i),
.wbs4_stb_o(pinmux_stb_i),
.wbs4_ack_i(pinmux_ack_o),
.wbs4_err_i(1'b0),
.wbs4_rty_i(1'b0),
.wbs4_cyc_o(pinmux_cyc_i),
.wbs4_addr(PINMUX_BASE_ADDR),
.wbs4_addr_msk(PINMUX_ADDR_MASK)
);
// Connect up GPIOs.
wire [31:0] io_in_internal;
// Internal wires for input ports.
assign io_in_internal = io_in[37:6];
assign pinmux_gpio_in = io_in_internal;
assign gpio_in[0] = io_in_internal;
assign gpio_in[1] = io_in_internal;
`ifdef HAS_CPU3
assign gpio_in[2] = io_in_internal;
`endif
`ifdef HAS_CPU4
assign gpio_in[3] = io_in_internal;
`endif
// assign uart_rx = io_in_internal[24];
assign flash_io0_di = io_in_internal[10-6];
assign flash_io1_di = io_in_internal[11-6];
assign flash_io2_di = io_in_internal[12-6];
assign flash_io3_di = io_in_internal[13-6];
assign io_out[5:0] = 6'b0;
assign io_oeb[5:0] = {6{1'b1}};
// TODO(hdpham): Add ability to disable or mux flash pins.
// TODO(hdpham): Add pin mux to remap UART and other peripheral pins.
// Internal wires for output ports to workaround LVS errors.
wire [31:0] io_out_internal;
wire [31:0] io_oeb_internal;
assign io_out_internal = gpio_out[0] |
gpio_out[1] |
`ifdef HAS_CPU3
gpio_out[2] |
`endif
`ifdef HAS_CPU4
gpio_out[3] |
`endif
{24'b0, flash_io3_do, flash_io2_do,
flash_io1_do, flash_io0_do, flash_clk,
flash_csb, 2'b0} |
pinmux_gpio_out;
//{6'b0, uart_tx, 25'b0};
assign io_oeb_internal = gpio_oeb[0] &
gpio_oeb[1] &
`ifdef HAS_CPU3
gpio_oeb[2] &
`endif
`ifdef HAS_CPU4
gpio_oeb[3] &
`endif
{{24{1'b1}}, flash_io3_oeb, flash_io2_oeb,
flash_io1_oeb, flash_io0_oeb, flash_clk_oeb,
flash_csb_oeb, 2'b11} &
pinmux_gpio_oeb;
//~{6'b0, uart_enabled, 25'b0};
wire [31:0] io_out_internal_buf;
wire [31:0] io_oeb_internal_buf;
// // Hack to manually insert buffer so LVS is happy.
// // TODO(hdpham): Wrap this to make non-technology specific.
// generate
// for (i = 0; i < 32; i = i + 1) begin
// sky130_fd_sc_hd__buf_8 out_buf (
// `ifdef SIM
// // TODO(hdpham): Figure out why the behavioral models don't work.
// .VPWR(1'b1),
// .VGND(1'b0),
// .VPB(1'b1),
// .VNB(1'b0),
// `endif
// .X(io_out_internal_buf[i]),
// .A(io_out_internal[i])
// );
// sky130_fd_sc_hd__buf_8 oeb_buf (
// `ifdef SIM
// .VPWR(1'b1),
// .VGND(1'b0),
// .VPB(1'b1),
// .VNB(1'b0),
// `endif
// .X(io_oeb_internal_buf[i]),
// .A(io_oeb_internal[i])
// );
// end
// endgenerate
assign io_out_internal_buf = io_out_internal;
assign io_oeb_internal_buf = io_oeb_internal;
assign io_out[37:6] = io_out_internal_buf;
assign io_oeb[37:6] = io_oeb_internal_buf;
assign la_data_out[31:0] = io_out_internal_buf;
assign la_data_out[63:32] = io_oeb_internal_buf;
// Tieoff unused.
// TODO(hdpham): Tie this to useful things.
assign la_data_out[127:64] = 64'b0;
endmodule // module softshell_top