123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- /*
- * top.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2020-2021 Sylvain Munaut <tnt@246tNt.com>
- * SPDX-License-Identifier: CERN-OHL-P-2.0
- */
- `default_nettype none
- `include "boards.vh"
- module top (
- // SPI
- `ifdef MEM_spi
- inout wire [3:0] spi_io,
- output wire spi_sck,
- output wire [1:0] spi_cs_n,
- `endif
- // HyperRAM
- `ifdef MEM_hyperram
- inout wire [7:0] hram_dq,
- inout wire hram_rwds,
- output wire hram_ck,
- output wire [3:0] hram_cs_n,
- output wire hram_rst_n,
- `endif
- // HDMI pads
- `ifdef VIDEO_4bpp
- output wire [ 3:0] hdmi_data,
- `endif
- `ifdef VIDEO_12bpp
- output wire [11:0] hdmi_data,
- `endif
- `ifndef VIDEO_none
- output wire hdmi_hsync,
- output wire hdmi_vsync,
- output wire hdmi_de,
- output wire hdmi_clk,
- `endif
- `ifdef HAS_UART
- // UART
- input wire uart_rx,
- output wire uart_tx,
- `endif
- `ifdef HAS_USB
- // USB
- inout wire usb_dp,
- inout wire usb_dn,
- output wire usb_pu,
- `endif
- // Clock (12M)
- input wire clk_in
- );
- // Target UART baudrate
- localparam integer BAUDRATE = 2000000;
- // Signals
- // -------
- // Control
- wire [31:0] aux_csr;
- wire dma_run;
- // Wishbone interface
- reg [31:0] wb_wdata;
- wire [95:0] wb_rdata;
- reg [15:0] wb_addr;
- reg wb_we;
- reg [ 2:0] wb_cyc;
- wire [ 2:0] wb_ack;
- // Memory interface
- wire [31:0] mi_addr;
- wire [ 6:0] mi_len;
- wire mi_rw;
- wire mi_valid;
- wire mi_ready;
- wire [31:0] mi_wdata;
- wire mi_wack;
- wire mi_wlast;
- wire [31:0] mi_rdata;
- wire mi_rstb;
- wire mi_rlast;
- // Memory interface - Memory Tester
- wire [31:0] mi0_addr;
- wire [ 6:0] mi0_len;
- wire mi0_rw;
- wire mi0_valid;
- wire mi0_ready;
- wire [31:0] mi0_wdata;
- wire mi0_wack;
- wire mi0_wlast;
- wire [31:0] mi0_rdata;
- wire mi0_rstb;
- wire mi0_rlast;
- // Memory interface - Video DMA
- wire [31:0] mi1_addr;
- wire [ 6:0] mi1_len;
- wire mi1_rw;
- wire mi1_valid;
- wire mi1_ready;
- wire [31:0] mi1_wdata;
- wire mi1_wack;
- wire mi1_wlast;
- wire [31:0] mi1_rdata;
- wire mi1_rstb;
- wire mi1_rlast;
- // Clock / Reset
- wire [3:0] clk_rd_delay;
- wire clk_1x;
- wire clk_2x;
- wire clk_4x;
- wire clk_rd;
- wire sync_4x;
- wire sync_rd;
- wire rst;
- wire clk_usb;
- wire rst_usb;
- wire bootloader;
- // Host interface
- // --------------
- `ifdef HAS_UART
- uart2wb #(
- .UART_DIV($rtoi((`SYS_FREQ / BAUDRATE) + 0.5)),
- `elsif HAS_USB
- muacm2wb #(
- `endif
- .WB_N(3)
- ) if_I (
- `ifdef HAS_UART
- .uart_rx (uart_rx),
- .uart_tx (uart_tx),
- `elsif HAS_USB
- .usb_dp (usb_dp),
- .usb_dn (usb_dn),
- .usb_pu (usb_pu),
- .usb_clk (clk_usb),
- .usb_rst (rst_usb),
- .bootloader (bootloader),
- `endif
- .wb_wdata (wb_wdata),
- .wb_rdata (wb_rdata),
- .wb_addr (wb_addr),
- .wb_we (wb_we),
- .wb_cyc (wb_cyc),
- .wb_ack (wb_ack),
- .aux_csr (aux_csr),
- .clk (clk_1x),
- .rst (rst)
- );
- assign dma_run = aux_csr[0];
- `ifdef HAS_USB
- SB_WARMBOOT warmboot (
- .BOOT (bootloader),
- .S0 (1'b1),
- .S1 (1'b0)
- );
- `endif
- // QSPI Controller
- // ---------------
- `ifdef MEM_spi
- // Config
- localparam integer PHY_SPEED = 4;
- localparam integer PL = (4 * PHY_SPEED) - 1;
- localparam integer CL = PHY_SPEED - 1;
- // Signals
- wire [PL:0] phy_io_i;
- wire [PL:0] phy_io_o;
- wire [ 3:0] phy_io_oe;
- wire [CL:0] phy_clk_o;
- wire [ 1:0] phy_cs_o;
- // Controller
- qpi_memctrl #(
- .CMD_READ (16'hEBEB),
- .CMD_WRITE (16'h0202),
- .DUMMY_CLK (6),
- .PAUSE_CLK (8),
- .FIFO_DEPTH (1),
- .N_CS (2),
- .PHY_SPEED (PHY_SPEED),
- .PHY_WIDTH (1),
- .PHY_DELAY ((PHY_SPEED == 1) ? 2 : ((PHY_SPEED == 2) ? 3 : 4))
- ) memctrl_I (
- .phy_io_i (phy_io_i),
- .phy_io_o (phy_io_o),
- .phy_io_oe (phy_io_oe),
- .phy_clk_o (phy_clk_o),
- .phy_cs_o (phy_cs_o),
- .mi_addr_cs (mi_addr[31:30]),
- .mi_addr ({mi_addr[21:0], 2'b00 }), /* 32 bits aligned */
- .mi_len (mi_len),
- .mi_rw (mi_rw),
- .mi_valid (mi_valid),
- .mi_ready (mi_ready),
- .mi_wdata (mi_wdata),
- .mi_wack (mi_wack),
- .mi_wlast (mi_wlast),
- .mi_rdata (mi_rdata),
- .mi_rstb (mi_rstb),
- .mi_rlast (mi_rlast),
- .wb_wdata (wb_wdata),
- .wb_rdata (wb_rdata[31:0]),
- .wb_addr (wb_addr[4:0]),
- .wb_we (wb_we),
- .wb_cyc (wb_cyc[0]),
- .wb_ack (wb_ack[0]),
- .clk (clk_1x),
- .rst (rst)
- );
- // PHY
- generate
- if (PHY_SPEED == 1)
- qpi_phy_ice40_1x #(
- .N_CS (2),
- .WITH_CLK (1),
- .NEG_IN (0)
- ) phy_I (
- .pad_io (spi_io),
- .pad_clk (spi_sck),
- .pad_cs_n (spi_cs_n),
- .phy_io_i (phy_io_i),
- .phy_io_o (phy_io_o),
- .phy_io_oe (phy_io_oe),
- .phy_clk_o (phy_clk_o),
- .phy_cs_o (phy_cs_o),
- .clk (clk_1x)
- );
- else if (PHY_SPEED == 2)
- qpi_phy_ice40_2x #(
- .N_CS (2),
- .WITH_CLK (1),
- ) phy_I (
- .pad_io (spi_io),
- .pad_clk (spi_sck),
- .pad_cs_n (spi_cs_n),
- .phy_io_i (phy_io_i),
- .phy_io_o (phy_io_o),
- .phy_io_oe (phy_io_oe),
- .phy_clk_o (phy_clk_o),
- .phy_cs_o (phy_cs_o),
- .clk_1x (clk_1x),
- .clk_2x (clk_2x)
- );
- else if (PHY_SPEED == 4)
- qpi_phy_ice40_4x #(
- .N_CS (2),
- .WITH_CLK (1),
- ) phy_I (
- .pad_io (spi_io),
- .pad_clk (spi_sck),
- .pad_cs_n (spi_cs_n),
- .phy_io_i (phy_io_i),
- .phy_io_o (phy_io_o),
- .phy_io_oe (phy_io_oe),
- .phy_clk_o (phy_clk_o),
- .phy_cs_o (phy_cs_o),
- .clk_1x (clk_1x),
- .clk_4x (clk_4x),
- .clk_sync (sync_4x)
- );
- endgenerate
- assign clk_rd_delay = 4'h0;
- `endif
- // HyperRAM Controller
- // -------------------
- `ifdef MEM_hyperram
- // Signals
- wire [ 1:0] phy_ck_en;
- wire [ 3:0] phy_rwds_in;
- wire [ 3:0] phy_rwds_out;
- wire [ 1:0] phy_rwds_oe;
- wire [31:0] phy_dq_in;
- wire [31:0] phy_dq_out;
- wire [ 1:0] phy_dq_oe;
- wire [ 3:0] phy_cs_n;
- wire phy_rst_n;
- wire [ 7:0] phy_cfg_wdata;
- wire [ 7:0] phy_cfg_rdata;
- wire phy_cfg_stb;
- // Controller
- hbus_memctrl hram_ctrl_I (
- .phy_ck_en (phy_ck_en),
- .phy_rwds_in (phy_rwds_in),
- .phy_rwds_out (phy_rwds_out),
- .phy_rwds_oe (phy_rwds_oe),
- .phy_dq_in (phy_dq_in),
- .phy_dq_out (phy_dq_out),
- .phy_dq_oe (phy_dq_oe),
- .phy_cs_n (phy_cs_n),
- .phy_rst_n (phy_rst_n),
- .phy_cfg_wdata (phy_cfg_wdata),
- .phy_cfg_rdata (phy_cfg_rdata),
- .phy_cfg_stb (phy_cfg_stb),
- .mi_addr_cs (mi_addr[31:30]),
- .mi_addr ({1'b0, mi_addr[29:0], 1'b0}), /* 32b aligned */
- .mi_len (mi_len),
- .mi_rw (mi_rw),
- .mi_linear (1'b0),
- .mi_valid (mi_valid),
- .mi_ready (mi_ready),
- .mi_wdata (mi_wdata),
- .mi_wmsk (4'h0),
- .mi_wack (mi_wack),
- .mi_rdata (mi_rdata),
- .mi_rstb (mi_rstb),
- .wb_wdata (wb_wdata),
- .wb_rdata (wb_rdata[31:0]),
- .wb_addr (wb_addr[3:0]),
- .wb_we (wb_we),
- .wb_cyc (wb_cyc[0]),
- .wb_ack (wb_ack[0]),
- .clk (clk_1x),
- .rst (rst)
- );
- // PHY
- hbus_phy_ice40 hram_phy_I (
- .hbus_dq (hram_dq),
- .hbus_rwds (hram_rwds),
- .hbus_ck (hram_ck),
- .hbus_cs_n (hram_cs_n),
- .hbus_rst_n (hram_rst_n),
- .phy_ck_en (phy_ck_en),
- .phy_rwds_in (phy_rwds_in),
- .phy_rwds_out (phy_rwds_out),
- .phy_rwds_oe (phy_rwds_oe),
- .phy_dq_in (phy_dq_in),
- .phy_dq_out (phy_dq_out),
- .phy_dq_oe (phy_dq_oe),
- .phy_cs_n (phy_cs_n),
- .phy_rst_n (phy_rst_n),
- .phy_cfg_wdata (phy_cfg_wdata),
- .phy_cfg_rdata (phy_cfg_rdata),
- .phy_cfg_stb (phy_cfg_stb),
- .clk_rd_delay (clk_rd_delay),
- .clk_1x (clk_1x),
- .clk_4x (clk_4x),
- .clk_rd (clk_rd),
- .sync_4x (sync_4x),
- .sync_rd (sync_rd)
- );
- `endif
- // Memory tester
- // -------------
- memtest #(
- .ADDR_WIDTH(32)
- ) memtest_I (
- .mi_addr (mi0_addr),
- .mi_len (mi0_len),
- .mi_rw (mi0_rw),
- .mi_valid (mi0_valid),
- .mi_ready (mi0_ready),
- .mi_wdata (mi0_wdata),
- .mi_wack (mi0_wack),
- .mi_rdata (mi0_rdata),
- .mi_rstb (mi0_rstb),
- .wb_wdata (wb_wdata),
- .wb_rdata (wb_rdata[63:32]),
- .wb_addr (wb_addr[8:0]),
- .wb_we (wb_we),
- .wb_cyc (wb_cyc[1]),
- .wb_ack (wb_ack[1]),
- .clk (clk_1x),
- .rst (rst)
- );
- // Memory Mux
- // ----------
- assign mi_addr = dma_run ? mi1_addr : mi0_addr;
- assign mi_len = dma_run ? mi1_len : mi0_len;
- assign mi_rw = dma_run ? mi1_rw : mi0_rw;
- assign mi_valid = dma_run ? mi1_valid : mi0_valid;
- assign mi0_ready = mi_ready & ~dma_run;
- assign mi1_ready = mi_ready & dma_run;
- assign mi_wdata = dma_run ? mi1_wdata : mi0_wdata;
- assign mi0_wack = mi_wack & ~dma_run;
- assign mi0_wlast = mi_wlast;
- assign mi1_wack = mi_wack & dma_run;
- assign mi1_wlast = mi_wlast;
- assign mi0_rdata = mi_rdata;
- assign mi0_rstb = mi_rstb & ~dma_run;
- assign mi0_rlast = mi_rlast;
- assign mi1_rdata = mi_rdata;
- assign mi1_rstb = mi_rstb & dma_run;
- assign mi1_rlast = mi_rlast;
- // HDMI output
- // -----------
- `ifndef VIDEO_none
- hdmi_out #(
- `ifdef VIDEO_4bpp
- .DW(4)
- `endif
- `ifdef VIDEO_12bpp
- .DW(12)
- `endif
- ) hdmi_I (
- .hdmi_data (hdmi_data),
- .hdmi_hsync (hdmi_hsync),
- .hdmi_vsync (hdmi_vsync),
- .hdmi_de (hdmi_de),
- .hdmi_clk (hdmi_clk),
- .wb_wdata (wb_wdata),
- .wb_rdata (wb_rdata[95:64]),
- .wb_addr (wb_addr[6:0]),
- .wb_we (wb_we),
- .wb_cyc (wb_cyc[2]),
- .wb_ack (wb_ack[2]),
- .mi_addr (mi1_addr),
- .mi_len (mi1_len),
- .mi_rw (mi1_rw),
- .mi_valid (mi1_valid),
- .mi_ready (mi1_ready),
- .mi_wdata (mi1_wdata),
- .mi_wack (mi1_wack),
- .mi_rdata (mi1_rdata),
- .mi_rstb (mi1_rstb),
- .clk_1x (clk_1x),
- .clk_4x (clk_4x),
- .sync_4x (sync_4x),
- .rst (rst)
- );
- `else
- // Dummy wishbone
- assign wb_ack[2] = wb_cyc[2];
- assign wb_rdata[95:64] = 32'h00000000;
- // Dummy mem-if
- assign mi1_addr = 32'hxxxxxxxx;
- assign mi1_len = 7'hxx;
- assign mi1_rw = 1'bx;
- assign mi1_valid = 1'b0;
- assign mi1_wdata = 32'hxxxxxxxx;
- `endif
- // Clock / Reset
- // -------------
- sysmgr sysmgr_I (
- .delay (clk_rd_delay),
- .clk_in (clk_in),
- .clk_1x (clk_1x),
- .clk_2x (clk_2x),
- .clk_4x (clk_4x),
- .clk_rd (clk_rd),
- .sync_4x (sync_4x),
- .sync_rd (sync_rd),
- .rst (rst),
- .clk_usb (clk_usb),
- .rst_usb (rst_usb)
- );
- endmodule
|