iso7816-test/gateware/iso7816soc/rtl/top.v

426 lines
7.4 KiB
Verilog

/*
* top.v
*
* vim: ts=4 sw=4
*
* Copyright (C) 2021 Sylvain Munaut <tnt@246tNt.com>
* SPDX-License-Identifier: CERN-OHL-P-2.0
*/
`default_nettype none
module top (
// USB
`ifdef WITH_USB
inout wire usb_dp,
inout wire usb_dn,
output wire usb_pu,
`endif
// SPI
inout wire spi_mosi,
inout wire spi_miso,
inout wire spi_clk,
output wire spi_flash_cs_n,
// Debug UART
input wire uart_rx,
output wire uart_tx,
// Button
input wire btn,
// NCN8025 breakout
output wire sc_rst,
inout wire [7:0] sc_io,
output wire sc_clk,
output wire sc_clkdiv1,
output wire sc_clkdiv2,
output wire sc_vsel0,
output wire sc_vsel1,
output wire sc_cmdvcc_n,
input wire sc_int_n,
// LED
output wire [2:0] rgb,
// Clock
input wire clk_in
);
localparam integer SC_N = 1;
localparam integer SPRAM_AW = 14; /* 14 => 64k, 15 => 128k */
localparam integer WB_N = 6 + SC_N;
localparam integer WB_DW = 32;
localparam integer WB_AW = 16;
localparam integer WB_RW = WB_DW * WB_N;
localparam integer WB_MW = WB_DW / 8;
genvar i;
// Signals
// -------
// Wishbone
wire [WB_AW-1:0] wb_addr;
wire [WB_DW-1:0] wb_rdata [0:WB_N-1];
wire [WB_RW-1:0] wb_rdata_flat;
wire [WB_DW-1:0] wb_wdata;
wire [WB_MW-1:0] wb_wmsk;
wire [WB_N -1:0] wb_cyc;
wire wb_we;
wire [WB_N -1:0] wb_ack;
// Misc IF
reg misc_ack;
wire misc_bus_clr;
reg misc_we_boot;
reg misc_we_gpio_oe;
reg misc_we_gpio_o;
wire [31:0] misc_rdata;
// WarmBoot
reg boot_now;
reg [ 1:0] boot_sel;
// GPIO
reg [ 7:0] gpio_oe;
reg [ 7:0] gpio_o;
wire [ 7:0] gpio_i;
// SC IO
wire [ 7:0] sc_io_i;
wire [ 7:0] sc_io_o;
wire [ 7:0] sc_io_oe;
// Clock / Reset logic
wire clk_sys;
wire rst;
// SoC
// ---
soc_picorv32_base #(
.WB_N (WB_N),
.WB_DW (WB_DW),
.WB_AW (WB_AW),
.SPRAM_AW(SPRAM_AW)
) base_I (
.wb_addr (wb_addr),
.wb_rdata(wb_rdata_flat),
.wb_wdata(wb_wdata),
.wb_wmsk (wb_wmsk),
.wb_we (wb_we),
.wb_cyc (wb_cyc),
.wb_ack (wb_ack),
.clk (clk_sys),
.rst (rst)
);
for (i=0; i<WB_N; i=i+1)
assign wb_rdata_flat[i*WB_DW+:WB_DW] = wb_rdata[i];
// Misc [0]
// --------
// Bus interface
// ACK & Clear
always @(posedge clk_sys)
misc_ack <= wb_cyc[0] & ~misc_ack;
assign wb_ack[0] = misc_ack;
assign misc_bus_clr = ~wb_cyc[0] | misc_ack;
// Write Enables
always @(posedge clk_sys)
if (misc_bus_clr) begin
misc_we_boot <= 1'b0;
misc_we_gpio_oe <= 1'b0;
misc_we_gpio_o <= 1'b0;
end else begin
misc_we_boot <= wb_we & (wb_addr[2:0] == 3'b000);
misc_we_gpio_oe <= wb_we & (wb_addr[2:0] == 3'b100);
misc_we_gpio_o <= wb_we & (wb_addr[2:0] == 3'b101);
end
// Registers
always @(posedge clk_sys)
if (rst) begin
boot_now <= 1'b0;
boot_sel <= 2'b00;
end else if (misc_we_boot) begin
boot_now <= wb_wdata[2];
boot_sel <= wb_wdata[1:0];
end
always @(posedge clk_sys)
if (rst)
gpio_oe <= 8'h00;
else if (misc_we_gpio_oe)
gpio_oe <= wb_wdata[7:0];
always @(posedge clk_sys)
if (rst)
gpio_o <= 8'h00;
else if (misc_we_gpio_o)
gpio_o <= wb_wdata[7:0];
// Read-Mux
always @(posedge clk_sys)
if (misc_bus_clr)
misc_rdata <= 0;
else
casez (wb_addr[2:0])
3'b100: misc_rdata <= { 24'h000000, gpio_oe };
3'b101: misc_rdata <= { 24'h000000, gpio_o };
3'b110: misc_rdata <= { 24'h000000, gpio_i };
default: misc_rdata <= 32'hxxxxxxxx;
endcase
assign wb_rdata[0] = misc_rdata;
// DFU Helper
dfu_helper #(
.TIMER_WIDTH(24),
.BTN_MODE(3),
.DFU_MODE(0)
) dfu_helper_I (
.boot_now(boot_now),
.boot_sel(boot_sel),
.btn_pad(btn),
.btn_val(),
.rst_req(),
.clk(clk_sys),
.rst(rst)
);
// ISO7816 GPIOs
// [7] clk_ena
// [6] int_n
// [5] rst
// [4] cmdvcc_n
// [3] vsel0
// [2] vsel1
// [1] clkdiv1
// [0] clkdiv2
// IOBs
SB_IO #(
.PIN_TYPE(6'b1101_00), // Reg input, Reg+RegOE output
.PULLUP(1'b0),
.IO_STANDARD("SB_LVCMOS")
) sc_ctrl_iob_I[6:0] (
.PACKAGE_PIN({
sc_int_n,
sc_rst,
sc_cmdvcc_n,
sc_vsel0,
sc_vsel1,
sc_clkdiv1,
sc_clkdiv2
}),
.INPUT_CLK (clk_sys),
.OUTPUT_CLK (clk_sys),
.D_IN_0 (gpio_i[6:0]),
.D_OUT_0 (gpio_o[6:0]),
.OUTPUT_ENABLE (gpio_oe[6:0]),
);
SB_IO #(
.PIN_TYPE(6'b1100_11),
.PULLUP(1'b0),
.IO_STANDARD("SB_LVCMOS")
) sc_clk_iob (
.PACKAGE_PIN (sc_clk),
.OUTPUT_CLK (clk_sys),
.D_OUT_0 (gpio_o[7]),
.D_OUT_1 (1'b0),
.OUTPUT_ENABLE (gpio_oe[7])
);
assign gpio_i[7] = gpio_o[7] & gpio_oe[7];
// UART [1]
// ----
uart_wb #(
.DIV_WIDTH(12),
.DW(WB_DW)
) uart_I (
.uart_tx (uart_tx),
.uart_rx (uart_rx),
.wb_addr (wb_addr[1:0]),
.wb_rdata (wb_rdata[1]),
.wb_we (wb_we),
.wb_wdata (wb_wdata),
.wb_cyc (wb_cyc[1]),
.wb_ack (wb_ack[1]),
.clk (clk_sys),
.rst (rst)
);
// SPI [2]
// ---
ice40_spi_wb #(
.N_CS(1),
.WITH_IOB(1),
.UNIT(0)
) spi_I (
.pad_mosi (spi_mosi),
.pad_miso (spi_miso),
.pad_clk (spi_clk),
.pad_csn (spi_flash_cs_n),
.wb_addr (wb_addr[3:0]),
.wb_rdata (wb_rdata[2]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[2]),
.wb_ack (wb_ack[2]),
.clk (clk_sys),
.rst (rst)
);
// RGB LEDs [3]
// --------
ice40_rgb_wb #(
.CURRENT_MODE("0b1"),
.RGB0_CURRENT("0b000001"),
.RGB1_CURRENT("0b000001"),
.RGB2_CURRENT("0b000001")
) rgb_I (
.pad_rgb (rgb),
.wb_addr (wb_addr[4:0]),
.wb_rdata (wb_rdata[3]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[3]),
.wb_ack (wb_ack[3]),
.clk (clk_sys),
.rst (rst)
);
// USB [4&5]
// ---
`ifdef WITH_USB
// Signals
wire clk_usb;
// Core
soc_usb usb_I (
.usb_dp (usb_dp),
.usb_dn (usb_dn),
.usb_pu (usb_pu),
.wb_addr (wb_addr[11:0]),
.wb_rdata (wb_rdata[4]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[5:4]),
.wb_ack (wb_ack[5:4]),
.usb_sof (),
.clk_sys (clk_sys),
.clk_48m (clk_usb),
.rst (rst)
);
assign wb_rdata[5] = 32'h00000000;
// Use HF OSC for 48 MHz
SB_HFOSC #(
.TRIM_EN ("0b0"),
.CLKHF_DIV ("0b00") // 48 MHz
) osc_I (
.CLKHFPU (1'b1),
.CLKHFEN (1'b1),
.CLKHF (clk_usb)
);
`else
// Dummy
assign wb_ack[4] = 1'b0;
assign wb_rdata[4] = 32'h00000000;
assign wb_ack[5] = 1'b0;
assign wb_rdata[5] = 32'h00000000;
`endif
// ISO7816 UART [6]
// ------------
// Core
for (i=0; i<SC_N; i=i+1)
begin
iso7816_wb #(
.EXT_IOREG(1)
) scuart_I (
.io_i (sc_io_i[i]),
.io_o (sc_io_o[i]),
.io_oe (sc_io_oe[i]),
.wb_addr (wb_addr[6:0]),
.wb_rdata (wb_rdata[6+i]),
.wb_wdata (wb_wdata),
.wb_we (wb_we),
.wb_cyc (wb_cyc[6+i]),
.wb_ack (wb_ack[6+i]),
.clk (clk_sys),
.rst (rst)
);
end
// IOB
SB_IO #(
.PIN_TYPE(6'b1101_00), // Reg input, Reg+RegOE output
.PULLUP(1'b1),
.IO_STANDARD("SB_LVCMOS")
) sc_iob_I[7:0] (
.PACKAGE_PIN (sc_io),
.INPUT_CLK (clk_sys),
.OUTPUT_CLK (clk_sys),
.D_IN_0 (sc_io_i),
.D_OUT_0 (sc_io_o),
.OUTPUT_ENABLE (sc_io_oe),
);
// Clock / Reset
// -------------
`ifdef SIM
reg clk_sys_s = 1'b0;
reg rst_s = 1'b1;
always #20.84 clk_sys_s <= !clk_sys_s;
initial begin
#200 rst_s = 0;
end
assign clk_sys = clk_sys_s;
assign rst = rst_s;
`else
sysmgr sys_mgr_I (
.clk_in (clk_in),
.rst_in (1'b0),
.clk_sys (clk_sys),
.rst_out (rst)
);
`endif
endmodule // top