]> git.the-white-hart.net Git - vhdl/commitdiff
Add updated host controller
authorrs <>
Fri, 19 Sep 2025 07:27:25 +0000 (02:27 -0500)
committerrs <>
Fri, 19 Sep 2025 07:27:25 +0000 (02:27 -0500)
libraries/nexys2/host_ctrl.vhd
libraries/nexys2/host_ctrl_opt.vhd [new file with mode: 0644]
libraries/nexys2/mem_wb_basic_opt.vhd [new file with mode: 0644]
libraries/utility/power_on_reset_opt.vhd [new file with mode: 0644]
libraries/utility/tests/test_por.vhd [new file with mode: 0644]
projects/cpu_0/nexys2_opt.vhd

index f80e4af26b122e59e88be1463320a21de7286bf0..a90e2672112ea3fb1b586f42db94547654837fb4 100644 (file)
@@ -288,7 +288,6 @@ architecture behavioral of host_ctrl is
 
        -- Control register signals
        signal ctrl:            std_logic_vector(7 downto 0);
-       signal flags:           std_logic_vector(7 downto 0);
 
        -- Out-of-band memory controller signals
        signal oob_mem_oe:      std_logic;
diff --git a/libraries/nexys2/host_ctrl_opt.vhd b/libraries/nexys2/host_ctrl_opt.vhd
new file mode 100644 (file)
index 0000000..e94a0da
--- /dev/null
@@ -0,0 +1,507 @@
+--------------------------------------------------------------------------------
+-- host_ctrl - Generic host control interface for Nexys2 board
+--
+-- Drop-in module that rovides host computer access to onboard memory, switches,
+-- LEDs, and signalling to any other device programmed to the FPGA
+--------------------------------------------------------------------------------
+-- Registers (Host EPP interface):
+--
+--      +---+---+---+---+---+---+---+---+
+--      | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+--      +---+---+---+---+---+---+---+---+
+-- 0x0  |RST|MEM|                       | CTRL
+--      +---+---+-----------------------+
+-- 0x1  |        MBOX_FLAGS(W1S)        |
+--      +-------------------------------+
+-- 0x2  |           MBOX_VALUE          |
+--      +-------------------------------+
+-- 0x3  |          SW(R)/LED(W)         |
+--      +-------------------------------+
+-- 0x4  |             SSEG0             |
+--      +-------------------------------+
+-- 0x5  |             SSEG1             |
+--      +-------------------------------+
+-- 0x6  |             SSEG2             |
+--      +-------------------------------+
+-- 0x7  |             SSEG3             |
+--      +---+---+---+---+---+---+---+---+
+-- 0x8  |FLS|FLS|   |   |   |RAM|RAM|AUT| MEM_CTRL
+--      |RST|CS |   |   |   |CS |CRE|CNT|
+--      +---+---+---+---+---+---+---+---+
+-- 0x9  |             ADDR_L            | (BIT 0 IGNORED)
+--      +-------------------------------+
+-- 0xa  |             ADDR_M            |
+--      +-------------------------------+
+-- 0xb  |             ADDR_H            |
+--      +-------------------------------+
+-- 0xc  |             DATA_L            | (TRANSFER TRIGGER)
+--      +-------------------------------+
+-- 0xd  |             DATA_H            |
+--      +-------------------------------+
+-- 0xe  |           (RESERVED)          |
+--      +-------------------------------+
+-- 0xf  |           (RESERVED)          |
+--      +-------------------------------+
+--
+-- CTRL
+-- Read-only
+-- RST - Active-high reset signal to device
+-- MEM - 1: Host computer controls onboard memory over USB-EPP interface
+--       0: Device controls onboard memory
+--
+-- MBOX_FLAGS
+-- Write-one-to-clear
+-- Eight independant signalling bits from the host computer to the device,
+-- intended for use as interrupt signals
+--
+-- MBOX_VALUE
+-- Eight-bit value readable and writable by both host and device, intended for
+-- small data transfers and signalling between host and device
+--
+-- SW(R)/LED(W)
+-- Readable and writable by both host and device
+-- Reads return the current positions of the switches on the Nexys2 board
+-- Writes set the state of the LEDs above the switches on the Nexys2 board
+--
+-- SSEGn
+-- Readable and writable by both host and device
+-- SSEG0 is the right-most (least-significant) seven-segment display
+-- SSEG3 is the left-most (most-significant) seven-segment display
+-- Values are active-low (segment is turned on when written to 0)
+-- Bit to segment mapping:
+--       (0)
+--     ------
+--    |      |
+-- (5)|      |(1)
+--    |  (6) |
+--     ------
+--    |      |
+-- (4)|      |(2)
+--    |      |
+--     ------   o(7)
+--       (3)
+--
+-- MEM_CTRL
+-- FLS_RST - Wired to the onboard flash reset signal, active low
+-- FLS_CS  - When clear, transfers go to the onboard flash
+-- RAM_CS  - When clear, transfers go to the onboard RAM
+-- RAM_CRE - Wired to the onboard RAM's CRE signal, active high
+-- AUT_CNT - Address auto-count, when set, increments addr by 2 each transaction
+-- Behavior when both FLS_CS and RAM_CS are clear is undefined
+--
+-- ADDR_L/M/H
+-- 24-bit address used for the memory transaction, treated as a byte-address,
+-- ADDR_L(0) is ignored
+--
+-- DATA_L/H
+-- 16-bit value read from or written to memory
+-- Reads/writes to DATA_L trigger a transaction:
+-- - For reads, read DATA_L first then DATA_H
+-- - For writes, write DATA_H first then DATA_L
+--
+--------------------------------------------------------------------------------
+-- Registers (Device Wishbone interface):
+--
+--    +---+---+---+---+---+---+---+---+
+--    | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+--    +---+---+---+---+---+---+---+---+
+-- 0  |RST|MEM|                       | CTRL(RO)
+--    +---+---+-----------------------+
+-- 1  |        MBOX_FLAGS(W1C)        |
+--    +-------------------------------+
+-- 2  |           MBOX_VALUE          |
+--    +-------------------------------+
+-- 3  |          SW(R)/LED(W)         |
+--    +-------------------------------+
+-- 4  |             SSEG0             |
+--    +-------------------------------+
+-- 5  |             SSEG1             |
+--    +-------------------------------+
+-- 6  |             SSEG2             |
+--    +-------------------------------+
+-- 7  |             SSEG3             |
+--    +-------------------------------+
+--
+-- CTRL
+-- Read-only
+-- RST - Active-high reset signal to device
+-- MEM - 1: Host computer controls onboard memory over USB-EPP interface
+--       0: Device controls onboard memory
+--
+-- MBOX_FLAGS
+-- Write-one-to-clear
+-- Eight independant signalling bits from the host computer to the device,
+-- intended for use as interrupt signals
+--
+-- MBOX_VALUE
+-- Eight-bit value readable and writable by both host and device, intended for
+-- small data transfers and signalling between host and device
+--
+-- SW(R)/LED(W)
+-- Readable and writable by both host and device
+-- Reads return the current positions of the switches on the Nexys2 board
+-- Writes set the state of the LEDs above the switches on the Nexys2 board
+--
+-- SSEGn
+-- Readable and writable by both host and device
+-- SSEG0 is the right-most (least-significant) seven-segment display
+-- SSEG3 is the left-most (most-significant) seven-segment display
+-- Values are active-low (segment is turned on when written to 0)
+-- Bit to segment mapping:
+--       (0)
+--     ------
+--    |      |
+-- (5)|      |(1)
+--    |  (6) |
+--     ------
+--    |      |
+-- (4)|      |(2)
+--    |      |
+--     ------   o(7)
+--       (3)
+--
+--------------------------------------------------------------------------------
+-- WISHBONE DATASHEET
+--
+-- Wishbone specification used: Rev B.3
+-- Interface type: device
+-- Port size: 8-bit
+-- Operand sizes: 8-bit
+-- Endianness: undefined (port size same as granularity)
+-- Data transfer sequence: undefined
+-- Clock constraints: none
+-- Signals:
+-- * rst_i
+-- * clk_i
+-- * d_cyc_i (CYC_I)
+-- * d_stb_i (STB_I)
+-- * d_we_i  (WE_I)
+-- * d_ack_o (ACK_O)
+-- * d_adr_i (ADR_I, 3-bit)
+-- * d_dat_i (DAT_I, 8-bit)
+-- * d_dat_o (DAT_O, 8-bit)
+--------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library utility;
+library work;
+
+
+entity host_ctrl_opt is
+       port (
+               -- Wishbone global signals
+               clk_i:        in    std_logic;
+               rst_i:        in    std_logic;
+
+               -- Signals to device
+               d_rst_o:      out   std_logic;
+               d_flags_o:    out   std_logic_vector(7 downto 0);
+               debug_i:      in    std_logic_vector(63 downto 0);
+               debug_o:      out   std_logic_vector(63 downto 0);
+
+               -- Device-side wishbone bus slave
+               d_cyc_i:      in    std_logic;
+               d_stb_i:      in    std_logic;
+               d_we_i:       in    std_logic;
+               d_ack_o:      out   std_logic;
+               d_adr_i:      in    std_logic_vector(2 downto 0);
+               d_dat_i:      in    std_logic_vector(7 downto 0);
+               d_dat_o:      out   std_logic_vector(7 downto 0);
+
+               -- Device memory interface
+               d_MemOE:      in    std_logic;
+               d_MemWR:      in    std_logic;
+               d_RamAdv:     in    std_logic;
+               d_RamCS:      in    std_logic;
+               d_RamClk:     in    std_logic;
+               d_RamCRE:     in    std_logic;
+               d_RamLB:      in    std_logic;
+               d_RamUB:      in    std_logic;
+               d_RamWait:    out   std_logic;
+               d_FlashRp:    in    std_logic;
+               d_FlashCS:    in    std_logic;
+               d_FlashStSts: out   std_logic;
+               d_MemAdr:     in    std_logic_vector(23 downto 1);
+               d_MemDB_o:    in    std_logic_vector(15 downto 0);  -- outbound - from device to memory
+               d_MemDB_i:    out   std_logic_vector(15 downto 0);  -- inbound - from memory to device
+
+               -- Nexys2 IO pins
+               EppAstb:      in    std_logic;
+               EppDstb:      in    std_logic;
+               EppWr:        in    std_logic;
+               EppDB:        inout std_logic_vector(7 downto 0);
+               EppWait:      out   std_logic;
+
+               MemOE:        out   std_logic;
+               MemWR:        out   std_logic;
+               RamAdv:       out   std_logic;
+               RamCS:        out   std_logic;
+               RamClk:       out   std_logic;
+               RamCRE:       out   std_logic;
+               RamLB:        out   std_logic;
+               RamUB:        out   std_logic;
+               RamWait:      in    std_logic;
+               FlashRp:      out   std_logic;
+               FlashCS:      out   std_logic;
+               FlashStSts:   in    std_logic;
+               MemAdr:       out   std_logic_vector(23 downto 1);
+               MemDB:        inout std_logic_vector(15 downto 0);
+
+               seg:          out   std_logic_vector(6 downto 0);
+               dp:           out   std_logic;
+               an:           out   std_logic_vector(3 downto 0);
+               Led:          out   std_logic_vector(7 downto 0);
+               sw:           in    std_logic_vector(7 downto 0)
+       );
+end host_ctrl_opt;
+
+
+architecture behavioral of host_ctrl_opt is
+
+       -- Internal reset from power-on-reset generator
+       -- Can be re-reset with rst_i, and is also sent to device
+       signal rst_int:         std_logic;
+
+       -- Host Wishbone bus from EPP bridge
+       signal h_cyc:           std_logic;
+       signal h_stb:           std_logic;
+       signal h_we:            std_logic;
+       signal h_ack:           std_logic;
+       signal h_adr:           std_logic_vector(7 downto 0);
+       signal h_dat_miso:      std_logic_vector(7 downto 0);
+       signal h_dat_mosi:      std_logic_vector(7 downto 0);
+
+       signal h_cyc_ctl:       std_logic;
+       signal h_dat_miso_ctl:  std_logic_vector(7 downto 0);
+       signal h_ack_ctl:       std_logic;
+
+       signal h_cyc_oob:       std_logic;
+       signal h_dat_miso_oob:  std_logic_vector(7 downto 0);
+       signal h_ack_oob:       std_logic;
+
+       signal h_cyc_deb:       std_logic;
+       signal h_dat_miso_deb:  std_logic_vector(7 downto 0);
+       signal h_ack_deb:       std_logic;
+
+       -- Control register signals
+       signal ctrl:            std_logic_vector(7 downto 0);
+
+       -- Out-of-band memory controller signals
+       signal oob_mem_oe:      std_logic;
+       signal oob_mem_wr:      std_logic;
+       signal oob_ram_adv:     std_logic;
+       signal oob_ram_cs:      std_logic;
+       signal oob_ram_clk:     std_logic;
+       signal oob_ram_cre:     std_logic;
+       signal oob_ram_ub:      std_logic;
+       signal oob_ram_lb:      std_logic;
+       signal oob_ram_wait:    std_logic;
+       signal oob_flash_rp:    std_logic;
+       signal oob_flash_cs:    std_logic;
+       signal oob_flash_ststs: std_logic;
+       signal oob_mem_adr:     std_logic_vector(23 downto 1);
+       signal oob_mem_db_i:    std_logic_vector(15 downto 0);
+       signal oob_mem_db_o:    std_logic_vector(15 downto 0);
+
+begin
+
+       -- Power-on-reset
+       e_por: entity utility.power_on_reset_opt
+               port map (
+                       rst_i => rst_i,
+                       clk_i => clk_i,
+                       rst_o => rst_int
+               );
+
+       d_rst_o <= rst_int or ctrl(7);
+
+       -- EPP to Wishbone bridge
+       e_epp_wb: entity work.epp_wb
+               port map (
+                       EppAstb => EppAstb,
+                       EppDstb => EppDstb,
+                       EppWr   => EppWr,
+                       EppDB   => EppDB,
+                       EppWait => EppWait,
+
+                       rst_i   => rst_int,
+                       clk_i   => clk_i,
+                       adr_o   => h_adr,
+                       dat_i   => h_dat_miso,
+                       dat_o   => h_dat_mosi,
+                       cyc_o   => h_cyc,
+                       stb_o   => h_stb,
+                       we_o    => h_we,
+                       ack_i   => h_ack
+               );
+
+
+       -- Host-side Wishbone multiplexer
+       e_wb_mapper: entity utility.wb_mapper_a8d8
+               generic map (N => 3)
+               port map (
+                       cyc_i    => h_cyc,
+                       ack_o    => h_ack,
+                       adr_i    => h_adr,
+                       dat_o    => h_dat_miso,
+
+                       mask(0)  => "00011000",
+                       mask(1)  => "00011000",
+                       mask(2)  => "00010000",
+
+                       match(0) => "00000000",
+                       match(1) => "00001000",
+                       match(2) => "00010000",
+
+                       cyc_o(0) => h_cyc_ctl,
+                       cyc_o(1) => h_cyc_oob,
+                       cyc_o(2) => h_cyc_deb,
+
+                       ack_i(0) => h_ack_ctl,
+                       ack_i(1) => h_ack_oob,
+                       ack_i(2) => h_ack_deb,
+
+                       dat_i(0) => h_dat_miso_ctl,
+                       dat_i(1) => h_dat_miso_oob,
+                       dat_i(2) => h_dat_miso_deb
+               );
+
+
+       -- Wishbone slave for control registers
+       e_host_regs: entity work.host_regs_opt
+               port map (
+                       rst_i   => rst_int,
+                       clk_i   => clk_i,
+
+                       h_cyc_i => h_cyc_ctl,
+                       h_stb_i => h_stb,
+                       h_we_i  => h_we,
+                       h_ack_o => h_ack_ctl,
+                       h_adr_i => h_adr(2 downto 0),
+                       h_dat_i => h_dat_mosi,
+                       h_dat_o => h_dat_miso_ctl,
+
+                       d_cyc_i => d_cyc_i,
+                       d_stb_i => d_stb_i,
+                       d_we_i  => d_we_i,
+                       d_ack_o => d_ack_o,
+                       d_adr_i => d_adr_i,
+                       d_dat_i => d_dat_i,
+                       d_dat_o => d_dat_o,
+
+                       ctrl    => ctrl,
+                       flags   => d_flags_o,
+                       seg     => seg,
+                       dp      => dp,
+                       an      => an,
+                       Led     => Led,
+                       sw      => sw
+               );
+
+
+       -- Wishbone slave for out-of-band memory controller
+       e_mem_oob: entity work.mem_wb_basic
+               port map (
+                       clk_i      => clk_i,
+                       rst_i      => rst_int,
+
+                       cyc_i      => h_cyc_oob,
+                       stb_i      => h_stb,
+                       we_i       => h_we,
+                       ack_o      => h_ack_oob,
+                       adr_i      => h_adr(2 downto 0),
+                       dat_i      => h_dat_mosi,
+                       dat_o      => h_dat_miso_oob,
+
+                       MemOE      => oob_mem_oe,
+                       MemWR      => oob_mem_wr,
+                       RamAdv     => oob_ram_adv,
+                       RamCS      => oob_ram_cs,
+                       RamClk     => oob_ram_clk,
+                       RamCRE     => oob_ram_cre,
+                       RamUB      => oob_ram_ub,
+                       RamLB      => oob_ram_lb,
+                       RamWait    => oob_ram_wait,
+                       FlashRp    => oob_flash_rp,
+                       FlashCS    => oob_flash_cs,
+                       FlashStSts => oob_flash_ststs,
+                       MemAdr     => oob_mem_adr,
+                       MemDB_i    => oob_mem_db_i,
+                       MemDB_o    => oob_mem_db_o
+               );
+
+
+       -- Wishbone slave for debug reads
+       e_debug: entity utility.wb_debug
+               port map (
+                       rst_i   => rst_int,
+                       clk_i   => clk_i,
+                       cyc_i   => h_cyc_deb,
+                       stb_i   => h_stb,
+                       we_i    => h_we,
+                       ack_o   => h_ack_deb,
+                       adr_i   => h_adr(2 downto 0),
+                       dat_i   => h_dat_mosi,
+                       dat_o   => h_dat_miso_deb,
+                       debug_i => debug_i,
+                       debug_o => debug_o
+               );
+
+
+       -- Memory multiplexer
+       e_mem_mux: entity work.mem_mux
+               port map (
+                       sel           => ctrl(6),
+
+                       s0_MemOE      => d_MemOE,
+                       s0_MemWR      => d_MemWR,
+                       s0_RamAdv     => d_RamAdv,
+                       s0_RamCS      => d_RamCS,
+                       s0_RamClk     => d_RamClk,
+                       s0_RamCRE     => d_RamCRE,
+                       s0_RamUB      => d_RamUB,
+                       s0_RamLB      => d_RamLB,
+                       s0_RamWait    => d_RamWait,
+                       s0_FlashRp    => d_FlashRp,
+                       s0_FlashCS    => d_FlashCS,
+                       s0_FlashStSts => d_FlashStSts,
+                       s0_MemAdr     => d_MemAdr,
+                       s0_MemDB_i    => d_MemDB_i,
+                       s0_MemDB_o    => d_MemDB_o,
+
+                       s1_MemOE      => oob_mem_oe,
+                       s1_MemWR      => oob_mem_wr,
+                       s1_RamAdv     => oob_ram_adv,
+                       s1_RamCS      => oob_ram_cs,
+                       s1_RamClk     => oob_ram_clk,
+                       s1_RamCRE     => oob_ram_cre,
+                       s1_RamUB      => oob_ram_ub,
+                       s1_RamLB      => oob_ram_lb,
+                       s1_RamWait    => oob_ram_wait,
+                       s1_FlashRp    => oob_flash_rp,
+                       s1_FlashCS    => oob_flash_cs,
+                       s1_FlashStSts => oob_flash_ststs,
+                       s1_MemAdr     => oob_mem_adr,
+                       s1_MemDB_i    => oob_mem_db_i,
+                       s1_MemDB_o    => oob_mem_db_o,
+
+                       MemOE         => MemOE,
+                       MemWR         => MemWR,
+                       RamAdv        => RamAdv,
+                       RamCS         => RamCS,
+                       RamClk        => RamClk,
+                       RamCRE        => RamCRE,
+                       RamUB         => RamUB,
+                       RamLB         => RamLB,
+                       RamWait       => RamWait,
+                       FlashRp       => FlashRp,
+                       FlashCS       => FlashCS,
+                       FlashStSts    => FlashStSts,
+                       MemAdr        => MemAdr,
+                       MemDB         => MemDB
+               );
+
+end behavioral;
diff --git a/libraries/nexys2/mem_wb_basic_opt.vhd b/libraries/nexys2/mem_wb_basic_opt.vhd
new file mode 100644 (file)
index 0000000..6b31202
--- /dev/null
@@ -0,0 +1,247 @@
+--------------------------------------------------------------------------------
+-- mem_wb_basic - Wishbone-bus interface for out-of-band memory programming
+--------------------------------------------------------------------------------
+-- Registers:
+--
+--    +---+---+---+---+---+---+---+---+
+--    | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+--    +---+---+---+---+---+---+---+---+
+-- 0: |FLS|FLS|   |   |   |RAM|RAM|AUT|  CTRL
+--    |RST|CS |   |   |   |CS |CRE|CNT|
+--    +---+---+---+---+---+---+---+---+
+-- 1: |            ADDR_L             |  A(0) IGNORED
+--    +-------------------------------+
+-- 2: |            ADDR_M             |
+--    +-------------------------------+
+-- 3: |            ADDR_H             |
+--    +-------------------------------+
+-- 4: |            DATA_L             |  TRIGGER
+--    +-------------------------------+
+-- 5: |            DATA_H             |
+--    +-------------------------------+
+-- 6: |          (RESERVED)           |
+--    +-------------------------------+
+-- 7: |          (RESERVED)           |
+--    +-------------------------------+
+--
+--------------------------------------------------------------------------------
+-- WISHBONE DATASHEET
+--
+-- Wishbone specification used: Rev B.3
+-- Interface type: device
+-- Port size: 8-bit
+-- Operand sizes: 8-bit
+-- Endianness: undefined (port size same as granularity)
+-- Data transfer sequence: undefined
+-- Clock constraints: none
+-- Signals:
+-- * rst_i
+-- * clk_i
+-- * cyc_i
+-- * stb_i
+-- * we_i
+-- * ack_o
+-- * adr_i (3-bit)
+-- * dat_i (8-bit)
+-- * dat_o (8-bit)
+--------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+
+entity mem_wb_basic_opt is
+       port (
+               -- Global wishbone signals
+               clk_i:      in  std_logic;
+               rst_i:      in  std_logic;
+
+               -- Wishbone bus signals
+               cyc_i:      in  std_logic;
+               stb_i:      in  std_logic;
+               we_i:       in  std_logic;
+               ack_o:      out std_logic;
+               adr_i:      in  std_logic_vector(2 downto 0);
+               dat_i:      in  std_logic_vector(7 downto 0);
+               dat_o:      out std_logic_vector(7 downto 0);
+
+               -- Memory interface signals
+               MemOE:      out std_logic;
+               MemWR:      out std_logic;
+               RamAdv:     out std_logic;
+               RamCS:      out std_logic;
+               RamClk:     out std_logic;
+               RamCRE:     out std_logic;
+               RamUB:      out std_logic;
+               RamLB:      out std_logic;
+               RamWait:    in  std_logic;
+               FlashRp:    out std_logic;
+               FlashCS:    out std_logic;
+               FlashStSts: in  std_logic;
+               MemAdr:     out std_logic_vector(23 downto 1);
+               MemDB_i:    in  std_logic_vector(15 downto 0);  -- Inbound: from memory to device
+               MemDB_o:    out std_logic_vector(15 downto 0)   -- Outbound: from device to memory
+       );
+end mem_wb_basic_opt;
+
+
+architecture behavioral of mem_wb_basic_opt is
+
+       type state is (S_READY, S_WAIT, S_DONE);
+
+       -- CTRL register bits:
+       -- 2 - ram_cre
+       -- 3 - ram_cs
+       -- 6 - flash_cs
+       -- 7 - flash_rp
+       signal ctrl_reg:     std_logic_vector( 7 downto 0);
+       signal addr_reg:     std_logic_vector(23 downto 0);
+       signal data_reg:     std_logic_vector(15 downto 0);
+
+       signal ctrl_fls_rst: std_logic;
+       signal ctrl_fls_cs:  std_logic;
+       signal ctrl_ram_cs:  std_logic;
+       signal ctrl_ram_cre: std_logic;
+       signal ctrl_aut_cnt: std_logic;
+
+       signal cur_state_reg: state;
+       signal next_state:    state;
+       signal data_latch:    std_logic;
+       signal addr_inc:      std_logic;
+
+       signal cyc_count_start: std_logic;
+       signal cyc_count_done:  std_logic;
+
+begin
+
+       -- Control signals
+       ctrl_fls_rst <= ctrl_reg(7);
+       ctrl_fls_cs  <= ctrl_reg(6);
+       ctrl_ram_cs  <= ctrl_reg(2);
+       ctrl_ram_cre <= ctrl_reg(1);
+       ctrl_aut_cnt <= ctrl_reg(0);
+
+       -- Memory signals
+       RamAdv  <= '0';
+       RamCS   <= ctrl_ram_cs or not cyc_i;  -- Gate RAM CS to allow refresh
+       RamClk  <= '0';
+       RamCRE  <= ctrl_ram_cre;
+       RamUB   <= '0';
+       RamLB   <= '0';
+       FlashRp <= ctrl_fls_rst;
+       FlashCS <= ctrl_fls_cs;
+       MemAdr  <= addr_reg(23 downto 1);
+       MemDB_o <= data_reg;
+
+       -- Wishbone signals
+       with adr_i select dat_o <=
+               ctrl_reg               when "000",
+               addr_reg( 7 downto  0) when "001",
+               addr_reg(15 downto  8) when "010",
+               addr_reg(23 downto 16) when "011",
+               data_reg( 7 downto  0) when "100",
+               data_reg(15 downto  8) when "101",
+               (others => '1')        when others;
+
+       -- Wishbone bus
+       process (clk_i, rst_i,
+                cyc_i, stb_i, we_i, adr_i, dat_i,
+                        cur_state_reg)
+       begin
+               if rising_edge(clk_i) then
+                       if rst_i = '1' then
+                               ctrl_reg <= "11000100";
+                               addr_reg <= (others => '0');
+                               data_reg <= (others => '0');
+                               cur_state_reg <= S_READY;
+                       else
+                               cur_state_reg <= next_state;
+
+                               if ctrl_aut_cnt = '1' and addr_inc = '1' then
+                                       addr_reg <= std_logic_vector(unsigned(addr_reg) + 2);
+                               end if;
+
+                               if cyc_i = '1' and stb_i = '1' and we_i = '1' then
+                                       case adr_i is
+                                               when "000"  => ctrl_reg               <= dat_i;
+                                               when "001"  => addr_reg( 7 downto  0) <= dat_i;
+                                               when "010"  => addr_reg(15 downto  8) <= dat_i;
+                                               when "011"  => addr_reg(23 downto 16) <= dat_i;
+                                               when "100"  => data_reg( 7 downto  0) <= dat_i;
+                                               when "101"  => data_reg(15 downto  8) <= dat_i;
+                                               when others => null;
+                                       end case;
+                               end if;
+
+                               if data_latch = '1' then
+                                       data_reg <= MemDB_i;
+                               end if;
+                       end if;
+               end if;
+       end process;
+
+
+       e_cyc_count: srl16
+               generic map (INIT => x"0000")
+               port map (
+                       clk => clk_i,
+                       a0  => '1',
+                       a1  => '1',
+                       a2  => '1',
+                       a3  => '0',
+                       d   => cyc_count_start,
+                       q   => cyc_count_done
+               );
+
+
+       process (cur_state_reg, cyc_count_done,
+                cyc_i, stb_i, we_i, adr_i)
+       begin
+               next_state <= cur_state_reg;
+               data_latch <= '0';
+               addr_inc   <= '0';
+               ack_o      <= '0';  -- TODO: test with this removed if it stops working
+               cyc_count_start <= '0';
+
+               MemOE <= '1';
+               MemWR <= '1';
+
+               case cur_state_reg is
+                       when S_READY =>
+                               if adr_i = "100" then
+                                       -- Reads/writes to DATA_LO trigger memory cycles,
+                                       -- which take longer than one clock cycle
+                                       ack_o <= '0';
+                                       if cyc_i = '1' and stb_i = '1' then
+                                               next_state <= S_WAIT;
+                                               cyc_count_start <= '1';
+                                       end if;
+                               else
+                                       ack_o <= '1';
+                               end if;
+
+                       when S_WAIT =>
+                               MemOE <= we_i;
+                               MemWR <= not we_i;
+                               if cyc_count_done = '1' then
+                                       data_latch <= not we_i;
+                                       next_state <= S_DONE;
+                               end if;
+
+                       when S_DONE =>
+                               MemOE <= we_i;
+                               MemWR <= '1';
+                               ack_o <= '1';
+                               addr_inc <= '1';
+                               next_state <= S_READY;
+
+                       when others =>
+                               next_state <= S_READY;
+               end case;
+       end process;
+
+end behavioral;
diff --git a/libraries/utility/power_on_reset_opt.vhd b/libraries/utility/power_on_reset_opt.vhd
new file mode 100644 (file)
index 0000000..befa900
--- /dev/null
@@ -0,0 +1,52 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use ieee.std_logic_misc.all;
+
+
+entity power_on_reset_opt is
+       port (
+               rst_i: in  std_logic;
+               clk_i: in  std_logic;
+               rst_o: out std_logic
+       );
+end power_on_reset_opt;
+
+
+architecture behavioral of power_on_reset_opt is
+
+       signal shift_reg:     std_logic_vector(1 downto 0) := (others => '1');
+       signal rst_sync:      std_logic;
+
+       signal count_reg:     std_logic_vector(3 downto 0) := (others => '1');
+       signal count_running: std_logic;
+
+begin
+
+       -- Synchronize external asynchronous reset to internal clock
+       process (rst_i, clk_i, shift_reg)
+       begin
+               if rst_i = '1' then
+                       shift_reg <= (others => '1');
+               elsif rising_edge(clk_i) then
+                       shift_reg <= '0' & shift_reg(shift_reg'high downto 1);
+               end if;
+       end process;
+       rst_sync <= shift_reg(0);
+
+       -- Continue to hold reset for 16 clock cycles to allow SRLs to flush
+       process (rst_sync, clk_i, count_reg, count_running)
+       begin
+               if rst_sync = '1' then
+                       count_reg <= (others => '1');
+               elsif rising_edge(clk_i) then
+                       if count_running = '1' then
+                               count_reg <= std_logic_vector(unsigned(count_reg) - 1);
+                       end if;
+               end if;
+       end process;
+       count_running <= or_reduce(count_reg);
+
+       rst_o <= count_running;
+
+end behavioral;
diff --git a/libraries/utility/tests/test_por.vhd b/libraries/utility/tests/test_por.vhd
new file mode 100644 (file)
index 0000000..9647b60
--- /dev/null
@@ -0,0 +1,48 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+library work;
+
+
+entity test_por is
+end test_por;
+
+
+architecture behavior of test_por is
+
+       constant CLK_PERIOD: time := 20 ns;
+
+       signal clk:   std_logic;
+       signal rst_i: std_logic;
+       signal rst_o: std_logic;
+
+begin
+
+       p_test: process
+       begin
+               rst_i <= '0';
+               wait for CLK_PERIOD * 20;
+               rst_i <= '1';
+               wait for CLK_PERIOD * 20;
+               rst_i <= '0';
+               wait;
+       end process;
+
+
+       e_uut: entity work.power_on_reset_opt
+               port map (
+                       rst_i => rst_i,
+                       clk_i => clk,
+                       rst_o => rst_o
+               );
+
+
+       p_clk: process
+       begin
+               clk <= '0';
+               wait for CLK_PERIOD / 2;
+               clk <= '1';
+               wait for CLK_PERIOD / 2;
+       end process;
+
+end;
index e2980be3cd2e084cf213ef4361ce6e4d15bd1630..cbf8dd4934fda5f11f5d41384e0fe011a17e3eae 100644 (file)
@@ -355,7 +355,7 @@ begin
 
 
        ints(1) <= or_reduce(host_flags);
-       e_host: entity nexys2_lib.host_ctrl
+       e_host: entity nexys2_lib.host_ctrl_opt
                port map (
                        clk_i        => d_clk,
                        rst_i        => '0',