--- /dev/null
+--------------------------------------------------------------------------------
+-- 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;
--- /dev/null
+--------------------------------------------------------------------------------
+-- 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;