426 lines
7.4 KiB
Verilog
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
|