From c67ed3f6a2fc8123225afccf844fd5e0e7752f7f Mon Sep 17 00:00:00 2001 From: rs <> Date: Fri, 19 Sep 2025 02:27:25 -0500 Subject: [PATCH] Add updated host controller --- libraries/nexys2/host_ctrl.vhd | 1 - libraries/nexys2/host_ctrl_opt.vhd | 507 +++++++++++++++++++++++ libraries/nexys2/mem_wb_basic_opt.vhd | 247 +++++++++++ libraries/utility/power_on_reset_opt.vhd | 52 +++ libraries/utility/tests/test_por.vhd | 48 +++ projects/cpu_0/nexys2_opt.vhd | 2 +- 6 files changed, 855 insertions(+), 2 deletions(-) create mode 100644 libraries/nexys2/host_ctrl_opt.vhd create mode 100644 libraries/nexys2/mem_wb_basic_opt.vhd create mode 100644 libraries/utility/power_on_reset_opt.vhd create mode 100644 libraries/utility/tests/test_por.vhd diff --git a/libraries/nexys2/host_ctrl.vhd b/libraries/nexys2/host_ctrl.vhd index f80e4af..a90e267 100644 --- a/libraries/nexys2/host_ctrl.vhd +++ b/libraries/nexys2/host_ctrl.vhd @@ -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 index 0000000..e94a0da --- /dev/null +++ b/libraries/nexys2/host_ctrl_opt.vhd @@ -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 index 0000000..6b31202 --- /dev/null +++ b/libraries/nexys2/mem_wb_basic_opt.vhd @@ -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 index 0000000..befa900 --- /dev/null +++ b/libraries/utility/power_on_reset_opt.vhd @@ -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 index 0000000..9647b60 --- /dev/null +++ b/libraries/utility/tests/test_por.vhd @@ -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; diff --git a/projects/cpu_0/nexys2_opt.vhd b/projects/cpu_0/nexys2_opt.vhd index e2980be..cbf8dd4 100644 --- a/projects/cpu_0/nexys2_opt.vhd +++ b/projects/cpu_0/nexys2_opt.vhd @@ -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', -- 2.43.0