From 33d725036fe1ad7a91e55e45d8a81a7894570e90 Mon Sep 17 00:00:00 2001 From: rs <> Date: Sun, 29 Jun 2025 17:20:26 -0500 Subject: [PATCH] Separate CYC for flash and ram in mem controller --- libraries/nexys2/mem_wb8_0.vhd | 26 +++++--- .../nexys2/tests/test_nexys2_mem_wb8_0.vhd | 54 +++++++++++------ libraries/nexys2/tests/test_sim_mem_wb8_0.vhd | 38 ++++++++---- libraries/utility/wb_mapper_a8d8.vhd | 59 +++++++++++++++++++ 4 files changed, 137 insertions(+), 40 deletions(-) create mode 100644 libraries/utility/wb_mapper_a8d8.vhd diff --git a/libraries/nexys2/mem_wb8_0.vhd b/libraries/nexys2/mem_wb8_0.vhd index a08602f..5999402 100644 --- a/libraries/nexys2/mem_wb8_0.vhd +++ b/libraries/nexys2/mem_wb8_0.vhd @@ -1,8 +1,9 @@ -------------------------------------------------------------------------------- -- mem_wb8_0 - Simple, non-caching 8-bit interface to Nexys2 onboard memory -- --- When adr_i(24) is clear, accesses go to flash --- When adr_i(24) is set, accesses go to RAM +-- Endianness of the interface is undefined, but for storage within the 16-bit +-- memory, little-endian ordering is used (even bytes are stored in the least- +-- significant byte, odd bytes are stored in the most-significant byte). -------------------------------------------------------------------------------- -- WISHBONE DATASHEET -- @@ -12,15 +13,16 @@ -- Operand sizes: 8-bit -- Endianness: undefined (port size same as granularity) -- Data transfer sequence: undefined --- Clock constraints: none +-- Clock constraints: max 50 MHz -- Signals: -- * rst_i -- * clk_i --- * cyc_i +-- * fls_cyc_i (CYC_I for flash) +-- * ram_cyc_i (CYC_I for RAM) -- * stb_i -- * we_i -- * ack_o --- * adr_i (25-bit) +-- * adr_i (24-bit) -- * dat_i (8-bit) -- * dat_o (8-bit) -------------------------------------------------------------------------------- @@ -38,11 +40,12 @@ entity mem_wb8_0 is clk_i: in std_logic; -- Wishbone system interface - cyc_i: in std_logic; + fls_cyc_i: in std_logic; + ram_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(24 downto 0); + adr_i: in std_logic_vector(23 downto 0); dat_i: in std_logic_vector(7 downto 0); dat_o: out std_logic_vector(7 downto 0); @@ -85,8 +88,13 @@ architecture behavioral of mem_wb8_0 is signal mdr_reg: std_logic_vector(15 downto 0); signal mdr_ld: std_logic; + -- Replacement for original cyc_i when separating cyc for ram and flash + signal cyc_i: std_logic; + begin + cyc_i <= fls_cyc_i or ram_cyc_i; + process (rst_i, clk_i, state_next) begin if rising_edge(clk_i) then @@ -136,13 +144,13 @@ begin end process; -- Little-endian memory interface - RamCS <= not (mem_enable and adr_i(24)); + RamCS <= not (mem_enable and ram_cyc_i); RamAdv <= '0'; RamClk <= '0'; RamCRE <= '0'; RamUB <= not adr_i(0); RamLB <= adr_i(0); - FlashCS <= not (mem_enable and (not adr_i(24))); + FlashCS <= not (mem_enable and fls_cyc_i); FlashRp <= '1'; MemAdr <= adr_i(23 downto 1); MemDB_o(15 downto 8) <= dat_i when adr_i(0) = '1' else (others => '0'); diff --git a/libraries/nexys2/tests/test_nexys2_mem_wb8_0.vhd b/libraries/nexys2/tests/test_nexys2_mem_wb8_0.vhd index d86880d..1abd80d 100644 --- a/libraries/nexys2/tests/test_nexys2_mem_wb8_0.vhd +++ b/libraries/nexys2/tests/test_nexys2_mem_wb8_0.vhd @@ -46,7 +46,8 @@ architecture behavioral of test_nexys2_mem_wb8_0 is signal clk: std_logic; signal rst: std_logic; signal cyc: std_logic; - signal mem_cyc: std_logic; + signal fls_cyc: std_logic; + signal ram_cyc: std_logic; signal host_cyc: std_logic; signal stb: std_logic; signal we: std_logic; @@ -54,7 +55,7 @@ architecture behavioral of test_nexys2_mem_wb8_0 is signal mem_ack: std_logic; signal host_ack: std_logic; signal adr: std_logic_vector(7 downto 0); - signal mem_adr: std_logic_vector(24 downto 0); + signal mem_adr: std_logic_vector(23 downto 0); signal dat_mosi: std_logic_vector(7 downto 0); signal dat_miso: std_logic_vector(7 downto 0); signal mem_miso: std_logic_vector(7 downto 0); @@ -80,13 +81,14 @@ architecture behavioral of test_nexys2_mem_wb8_0 is begin - mem_adr <= adr(6) & "000000000000000000" & adr(5 downto 0); + mem_adr <= "000000000000000000" & adr(5 downto 0); e_mem: entity work.mem_wb8_0 port map ( rst_i => rst, clk_i => clk, - cyc_i => mem_cyc, + fls_cyc_i => fls_cyc, + ram_cyc_i => ram_cyc, stb_i => stb, we_i => we, ack_o => mem_ack, @@ -113,26 +115,39 @@ begin MemDB_o => d_MemDB_o ); - e_wb_mux: entity utility.wb_mux2 + + e_mapper: entity utility.wb_mapper_a8d8 generic map ( - WIDTH => 8 + N => 3 ) port map ( - sel => adr(7), - - cyc_i => cyc, - ack_o => ack, - dat_o => dat_miso, - - cyc_o_0 => mem_cyc, - ack_i_0 => mem_ack, - dat_i_0 => mem_miso, - - cyc_o_1 => host_cyc, - ack_i_1 => host_ack, - dat_i_1 => host_miso + cyc_i => cyc, + ack_o => ack, + adr_i => adr, + dat_o => dat_miso, + + mask(0) => "11000000", + mask(1) => "11000000", + mask(2) => "11000000", + + match(0) => "00000000", + match(1) => "01000000", + match(2) => "10000000", + + cyc_o(0) => fls_cyc, + cyc_o(1) => ram_cyc, + cyc_o(2) => host_cyc, + + ack_i(0) => mem_ack, + ack_i(1) => mem_ack, + ack_i(2) => host_ack, + + dat_i(0) => mem_miso, + dat_i(1) => mem_miso, + dat_i(2) => host_miso ); + e_wb_dbg: entity work.wishbone_debugger port map ( clk_o => clk, @@ -154,6 +169,7 @@ begin btn => btn ); + e_host_ctrl: entity work.host_ctrl port map ( clk_i => clk, diff --git a/libraries/nexys2/tests/test_sim_mem_wb8_0.vhd b/libraries/nexys2/tests/test_sim_mem_wb8_0.vhd index 64e2956..60c142e 100644 --- a/libraries/nexys2/tests/test_sim_mem_wb8_0.vhd +++ b/libraries/nexys2/tests/test_sim_mem_wb8_0.vhd @@ -17,11 +17,12 @@ architecture behavior of test_sim_mem_wb8_0 is signal rst_i: std_logic; signal clk_i: std_logic; - signal cyc_i: std_logic; + signal fls_cyc_i: std_logic; + signal ram_cyc_i: std_logic; signal stb_i: std_logic; signal we_i: std_logic; signal ack_o: std_logic; - signal adr_i: std_logic_vector(24 downto 0); + signal adr_i: std_logic_vector(23 downto 0); signal dat_i: std_logic_vector(7 downto 0); signal dat_o: std_logic_vector(7 downto 0); @@ -46,7 +47,8 @@ architecture behavior of test_sim_mem_wb8_0 is type test_name_t is ( NONE, - RD_FLASH + RD_FLASH, + RD_RAM ); signal test: test_name_t; @@ -57,7 +59,8 @@ begin begin -- Initial values test <= NONE; - cyc_i <= '0'; + fls_cyc_i <= '0'; + ram_cyc_i <= '0'; stb_i <= '0'; we_i <= '0'; adr_i <= (others => '0'); @@ -71,14 +74,24 @@ begin wait for 300 ns; -- T_PHEL for flash -- Read from flash - test <= RD_FLASH; - cyc_i <= '1'; - stb_i <= '1'; - we_i <= '0'; - adr_i <= "0000000000000000000000000"; + test <= RD_FLASH; + fls_cyc_i <= '1'; + stb_i <= '1'; + we_i <= '0'; + adr_i <= "000000000000000000000000"; wait until ack_o = '1'; - cyc_i <= '0'; - stb_i <= '0'; + fls_cyc_i <= '0'; + stb_i <= '0'; + + -- Read from RAM + test <= RD_RAM; + ram_cyc_i <= '1'; + stb_i <= '1'; + we_i <= '0'; + adr_i <= "000000000000000000000000"; + wait until ack_o = '1'; + ram_cyc_i <= '0'; + stb_i <= '0'; wait; end process; @@ -88,7 +101,8 @@ begin rst_i => rst_i, clk_i => clk_i, - cyc_i => cyc_i, + fls_cyc_i => fls_cyc_i, + ram_cyc_i => ram_cyc_i, stb_i => stb_i, we_i => we_i, ack_o => ack_o, diff --git a/libraries/utility/wb_mapper_a8d8.vhd b/libraries/utility/wb_mapper_a8d8.vhd new file mode 100644 index 0000000..ca27523 --- /dev/null +++ b/libraries/utility/wb_mapper_a8d8.vhd @@ -0,0 +1,59 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_misc.all; + +library work; +use work.types.all; + + +entity wb_mapper_a8d8 is + generic ( + N: integer := 8 + ); + port ( + -- Master interface + cyc_i: in std_logic; + ack_o: out std_logic; + adr_i: in slv8; + dat_o: out slv8; + + -- Configuration + mask: in slv8_array(N-1 downto 0); + match: in slv8_array(N-1 downto 0); + + -- Device interfaces + cyc_o: out std_logic_vector(N-1 downto 0); + ack_i: in std_logic_vector(N-1 downto 0); + dat_i: in slv8_array(N-1 downto 0) + ); +end wb_mapper_a8d8; + + +architecture behavioral of wb_mapper_a8d8 is + + signal sel: std_logic_vector(N-1 downto 0); + signal dummy: std_logic; + +begin + + g_sel: for n in 0 to n-1 generate + sel(n) <= '1' when (adr_i and mask(n)) = match(n) else '0'; + end generate; + dummy <= not or_reduce(sel); + + cyc_o <= sel when cyc_i = '1' else (others => '0'); + ack_o <= or_reduce(sel and ack_i) or dummy; + + process (sel, dat_i) + variable temp: slv8 := (others => '0'); + begin + temp := (others => '0'); + for n in 0 to N-1 loop + if sel(n) = '1' then + temp := temp or dat_i(n); + end if; + end loop; + dat_o <= temp; + end process; + +end behavioral; -- 2.43.0