diff --git a/lib/JBUS/src/busmaster_async.vhd b/lib/JBUS/src/busmaster_async.vhd new file mode 100644 index 0000000..d3ffc5a --- /dev/null +++ b/lib/JBUS/src/busmaster_async.vhd @@ -0,0 +1,226 @@ +----------------------------------------------------------------------- +-- $Header: /tmp/cvsroot/VHDL/lib/JBUS/src/busmaster_async.vhd,v 1.1 2013-07-21 09:21:30 jens Exp $ +----------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +use work.utils_pkg.all; +use work.busmaster_types.all; + +------------------------------------------------------------------ +entity busmaster_async is + Generic + ( + DATA_WIDTH : natural := 32; + FIFO_DEPTH : natural := 4 + ); + Port + ( + clk : in std_logic; + rst : in std_logic; + + cmd_cycle_finished : out std_logic; + cmd_cycle_en : in std_logic; + cmd_rdy : out std_logic; + cmd_we : in std_logic; + + cmd_in : in bm_cmd_t; + + din : in unsigned(DATA_WIDTH-1 downto 0); + din_rdy : out std_logic; + din_we : in std_logic; + + dout : out unsigned(DATA_WIDTH-1 downto 0); + dout_vld : out std_logic; + dout_re : in std_logic; + + -- J-BUS signals + RST_I : in STD_LOGIC; + CLK_I : in STD_LOGIC; + ACK_I : in std_logic; + SRDY_I : in std_logic; + MDAT_I : in unsigned(DATA_WIDTH-1 downto 0); + MDAT_O : out unsigned(DATA_WIDTH-1 downto 0); + ADDR_O : out unsigned(31 downto 0); + SEL_O : out unsigned(DATA_WIDTH/8-1 downto 0); + WE_O : out std_logic; + CYC_O : out std_logic; + STB_O : out std_logic; + MRDY_O : out std_logic + ); + end busmaster_async; + +architecture Behavioral of busmaster_async is + + -- Bus Command FIFO + signal cmd_fifo_din : unsigned(32+DATA_WIDTH/8+1-1 downto 0); + signal cmd_fifo_dout : unsigned(32+DATA_WIDTH/8+1-1 downto 0); + signal cmd_fifo_re : std_logic; + signal cmd_fifo_we : std_logic; + signal cmd_fifo_full : std_logic; + signal cmd_fifo_empty : std_logic; + + -- Bus Read FIFO + signal read_fifo_re : std_logic; + signal read_fifo_we : std_logic; + signal read_fifo_full : std_logic; + signal read_fifo_empty : std_logic; + signal write_fifo_re : std_logic; + signal write_fifo_we : std_logic; + signal write_fifo_full : std_logic; + signal write_fifo_empty : std_logic; + signal cycle_busy : std_logic; + signal cmd_en : std_logic; + signal cmd_read_en : std_logic; + signal read_cnt : integer range 0 to 65535; + signal write : std_logic; + + signal jbus_cycle_busy : std_logic; + +begin + + cmd_en <= cmd_cycle_en and cmd_we and not cmd_fifo_full; + cmd_read_en <= cmd_en and not cmd_in.rw; + write <= cmd_fifo_dout(32+DATA_WIDTH/8); + + dout_vld <= not read_fifo_empty; + MRDY_O <= not read_fifo_full; + read_fifo_we <= ACK_I and jbus_cycle_busy; + read_fifo_re <= dout_re; + ADDR_O <= cmd_fifo_dout(31 downto 0); + SEL_O <= cmd_fifo_dout(32+DATA_WIDTH/8-1 downto 32); + WE_O <= write; + + cmd_fifo_din <= cmd_in.rw & cmd_in.sel & cmd_in.addr; + + cmd_rdy <= not cmd_fifo_full; + + cmd_fifo_we <= cmd_en; + cmd_fifo_re <= SRDY_I and jbus_cycle_busy; + + din_rdy <= not write_fifo_full; + write_fifo_we <= din_we; + write_fifo_re <= SRDY_I and jbus_cycle_busy and write and not cmd_fifo_empty; + + CYC_O <= jbus_cycle_busy; + STB_O <= not cmd_fifo_empty; + + +-- J-Bus domain +proc_JBUS_to_local_cmd_cycle_finished: + process(clk) + begin + if rising_edge(clk) then + cmd_cycle_finished <= not jbus_cycle_busy; + end if; + end process; + +proc_JBUS_cycle: + process(CLK_I) + begin + if rising_edge(CLK_I) then + jbus_cycle_busy <= cycle_busy; + end if; + end process; + +proc_bus_read_counter: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + read_cnt <= 0; + elsif cmd_read_en = '1' and read_fifo_empty = '1' then + read_cnt <= read_cnt + 1; + elsif cmd_read_en = '0' and read_fifo_empty = '0' and dout_re = '1' then + read_cnt <= read_cnt - 1; + end if; + end if; + end process; + +proc_cycle_busy: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + cycle_busy <= '0'; + elsif cmd_cycle_en = '1' then + if cmd_we = '1' then + cycle_busy <= '1'; + end if; + elsif read_cnt = 0 and cmd_fifo_empty = '1' then + cycle_busy <= '0'; + end if; + end if; + end process; + +-- Bus READ FIFO +inst_BM_READ_FIFO: entity work.fifo_async + GENERIC MAP + ( + addr_width => NextExpBaseTwo(FIFO_DEPTH), + data_width => DATA_WIDTH, + do_last_read_update => true + ) + PORT MAP + ( + rst => rst, + clk_r => clk, + clk_w => CLK_I, + we => read_fifo_we, + re => read_fifo_re, + fifo_full => read_fifo_full, + fifo_empty => read_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_r => dout, + data_w => MDAT_I + ); + +-- Bus WRITE FIFO +inst_BM_WRITE_FIFO: entity work.fifo_async + GENERIC MAP + ( + addr_width => NextExpBaseTwo(FIFO_DEPTH), + data_width => DATA_WIDTH, + do_last_read_update => false + ) + PORT MAP + ( + rst => rst, + clk_r => CLK_I, + clk_w => clk, + we => write_fifo_we, + re => write_fifo_re, + fifo_full => write_fifo_full, + fifo_empty => write_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_r => MDAT_O, + data_w => din + ); + +-- Bus command FIFO +inst_BM_CMD_FIFO: entity work.fifo_async + GENERIC MAP + ( + addr_width => NextExpBaseTwo(FIFO_DEPTH), + data_width => cmd_fifo_din'length, + do_last_read_update => false + ) + PORT MAP + ( + rst => rst, + clk_r => CLK_I, + clk_w => clk, + we => cmd_fifo_we, + re => cmd_fifo_re, + fifo_full => cmd_fifo_full, + fifo_empty => cmd_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_r => cmd_fifo_dout, + data_w => cmd_fifo_din + ); + +end Behavioral; diff --git a/lib/JBUS/src/tb_busmaster_async.vhd b/lib/JBUS/src/tb_busmaster_async.vhd new file mode 100644 index 0000000..353d7d8 --- /dev/null +++ b/lib/JBUS/src/tb_busmaster_async.vhd @@ -0,0 +1,451 @@ +----------------------------------------------------------------------- +-- $Header: /tmp/cvsroot/VHDL/lib/JBUS/src/tb_busmaster_async.vhd,v 1.1 2013-07-21 09:21:30 jens Exp $ +----------------------------------------------------------------------- + +LIBRARY ieee; +use IEEE.STD_LOGIC_1164.ALL; +USE ieee.numeric_std.ALL; + +use work.busmaster_types.all; + +ENTITY tb_busmaster_async IS +END tb_busmaster_async; + +ARCHITECTURE behavior OF tb_busmaster_async IS + + constant DATA_WIDTH : integer := 32; + constant CLK_PERIOD : time := 10 ns; + constant JBUS_CLK_PERIOD : time := 20 ns; + signal clk : std_logic := '1'; + signal rst : std_logic := '1'; + + signal CLK_O : std_logic := '1'; + signal RST_O : std_logic := '1'; + + -- Master + signal INT_O : std_logic; + signal CYC_O : std_logic; + signal STB_O : std_logic; + signal WE_O : std_logic; + signal SEL_O : unsigned(3 downto 0) := (others => '1'); + signal ACK_I : std_logic := '0'; + signal MRDY_O : std_logic := '1'; + signal SRDY_I : std_logic := '0'; + signal ADDR_O : unsigned(31 downto 0) := (others => '-'); + signal MDAT_I_64 : unsigned(63 downto 0) := (others => '-'); + signal MDAT_O_64 : unsigned(63 downto 0) := (others => '-'); + + signal MDAT_I : unsigned(31 downto 0) := (others => '-'); + signal MDAT_O : unsigned(31 downto 0) := (others => '-'); + + signal cmd_cycle_finished : std_logic; + signal cmd_cycle_en : std_logic := '0'; + signal cmd_rdy : std_logic; + signal cmd_we : std_logic := '0'; + + signal cmd_in : bm_cmd_t; + + signal din : unsigned(31 downto 0) := (others => '-'); + signal din_rdy : std_logic; + signal din_we : std_logic := '0'; + + signal dout : unsigned(31 downto 0); + signal dout_vld : std_logic; + signal dout_re : std_logic := '0'; + + signal read_reg : unsigned(31 downto 0) := (others => '-'); + + type state_t is (IDLE, LA_SA, LA_SU, LU_SA, LU_SU, CC_SA, CC_SU); + signal state : state_t := IDLE; + + type ram_t is array (0 to 127) of unsigned(63 downto 0); + + signal ram64 : ram_t := + ( + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000" + + ); + +BEGIN + + MDAT_I <= MDAT_I_64(31 downto 0); + MDAT_O_64 <= MDAT_O & MDAT_O; + +inst_uut : entity work.busmaster_async + GENERIC MAP + ( + DATA_WIDTH => 32, + FIFO_DEPTH => 2 + ) + PORT MAP + ( + -- System signals + rst => rst, + clk => clk, + + cmd_cycle_finished => cmd_cycle_finished, + cmd_cycle_en => cmd_cycle_en, + cmd_rdy => cmd_rdy, + cmd_we => cmd_we, + cmd_in => cmd_in, + + din => din, + din_rdy => din_rdy, + din_we => din_we, + + dout => dout, + dout_vld => dout_vld, + dout_re => dout_re, + + -- JBUS Master signals + RST_I => RST_O, + CLK_I => CLK_O, + CYC_O => CYC_O, + STB_O => STB_O, + WE_O => WE_O, + SEL_O => SEL_O, + ACK_I => ACK_I, + SRDY_I => SRDY_I, + MRDY_O => MRDY_O, + ADDR_O => ADDR_O, + MDAT_I => MDAT_I, + MDAT_O => MDAT_O + ); + +CLK_GEN: process + begin + wait for CLK_PERIOD/2; + clk <= not clk; + end process; + +JBUS_CLK_GEN: process + begin + wait for JBUS_CLK_PERIOD/2; + CLK_O <= not CLK_O; + end process; + +-- Slave + SRDY_I <= CYC_O; + + process(CLK_O) + variable res: unsigned(63 downto 0); + variable ram_data : unsigned(63 downto 0); + begin + if rising_edge(CLK_O) then + if RST_O = '1' then + else + ACK_I <= '0'; + if (CYC_O and STB_O) = '1' then + if WE_O = '0' then + ACK_I <= '1'; + ram_data := ram64(to_integer(ADDR_O(31 downto 3))); + if ADDR_O(2) = '0' then + res := ram_data; + else + res := ram_data(31 downto 0) & ram_data(63 downto 32); + end if; + elsif MRDY_O = '1' then -- WE=1 + ram_data := ram64(to_integer(ADDR_O(31 downto 3))); + ram_data := (others => '-'); + if ADDR_O(2) = '0' then + if SEL_O = "11111111" then + ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64; + elsif SEL_O = "00001111" then + ram64(to_integer(ADDR_O(31 downto 3))) <= ram_data(63 downto 32) & MDAT_O_64(31 downto 0); + elsif SEL_O = "11110000" then + ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(63 downto 32) & ram_data(31 downto 0); + end if; + else + if SEL_O = "11111111" then + ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(31 downto 0) & MDAT_O_64(63 downto 32); + elsif SEL_O = "00001111" then + ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(31 downto 0) & ram_data(31 downto 0); + elsif SEL_O = "11110000" then + ram64(to_integer(ADDR_O(31 downto 3))) <= ram_data(63 downto 32) & MDAT_O_64(63 downto 32); + end if; + end if; + end if; + end if; + if (CYC_O and MRDY_O) = '1' then + MDAT_I_64 <= res; + end if; + end if; + end if; + end process; + + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + read_reg <= X"00000000"; + elsif dout_vld = '1' then + read_reg <= dout; + end if; + end if; + end process; + dout_re <= dout_vld; + +-- Master +STIMULUS: process + + variable result : unsigned(31 downto 0); + + procedure cmd_write_single(addr, sel, data : unsigned) is + begin + + din <= data; + din_we <= '1'; + wait until rising_edge(clk) and din_rdy = '1'; + din_we <= '0'; + + cmd_in.rw <= '1'; + cmd_in.sel <= sel; + cmd_in.addr <= addr; + cmd_we <= '1'; + wait until rising_edge(clk) and cmd_rdy = '1'; + cmd_we <= '0'; + + end procedure cmd_write_single; + + procedure cmd_read_single(addr : unsigned) is + begin + + cmd_in.rw <= '0'; + cmd_in.sel <= (others => '0'); + cmd_in.addr <= addr; + cmd_we <= '1'; + wait until rising_edge(clk) and cmd_rdy = '1'; + cmd_we <= '0'; + + end procedure cmd_read_single; + + begin + + wait for 6*CLK_PERIOD; + rst <= '0'; + RST_O <= '0'; + wait for 60*CLK_PERIOD; + wait until rising_edge(clk); + state <= IDLE; + + for i in 0 to 9 loop + + cmd_cycle_en <= '1'; + cmd_write_single(X"0000_0000", "1111", X"1000_ABCD"); + cmd_write_single(X"0000_0008", "1111", X"2000_ABCD"); + cmd_write_single(X"0000_0010", "1111", X"3000_ABCD"); + cmd_write_single(X"0000_0018", "1111", X"4000_ABCD"); + cmd_write_single(X"0000_0020", "1111", X"5000_ABCD"); + cmd_write_single(X"0000_0028", "1111", X"6000_ABCD"); + cmd_write_single(X"0000_0030", "1111", X"7000_ABCD"); + cmd_write_single(X"0000_0038", "1111", X"8000_ABCD"); + cmd_read_single(X"0000_0000"); + cmd_read_single(X"0000_0008"); + cmd_read_single(X"0000_0010"); + cmd_read_single(X"0000_0018"); + cmd_read_single(X"0000_0020"); + cmd_read_single(X"0000_0028"); + cmd_read_single(X"0000_0030"); + cmd_read_single(X"0000_0038"); + cmd_write_single(X"0000_0000", "1111", X"1000_BEEF"); + cmd_read_single(X"0000_0000"); + cmd_write_single(X"0000_0008", "1111", X"2000_BEEF"); + cmd_read_single(X"0000_0008"); + cmd_write_single(X"0000_0010", "1111", X"3000_BEEF"); + cmd_read_single(X"0000_0010"); + cmd_write_single(X"0000_0018", "1111", X"4000_BEEF"); + cmd_read_single(X"0000_0018"); + cmd_write_single(X"0000_0020", "1111", X"5000_BEEF"); + cmd_read_single(X"0000_0020"); + cmd_write_single(X"0000_0028", "1111", X"6000_BEEF"); + cmd_read_single(X"0000_0028"); + cmd_write_single(X"0000_0030", "1111", X"7000_BEEF"); + cmd_read_single(X"0000_0030"); + cmd_write_single(X"0000_0038", "1111", X"8000_BEEF"); + cmd_read_single(X"0000_0038"); + cmd_cycle_en <= '0'; + wait until rising_edge(clk); + wait until rising_edge(clk); + cmd_cycle_en <= '1'; + cmd_write_single(X"0000_0100", "1111", X"1100_ABCD"); + cmd_write_single(X"0000_0108", "1111", X"2200_ABCD"); + cmd_write_single(X"0000_0110", "1111", X"3300_ABCD"); + cmd_write_single(X"0000_0118", "1111", X"4400_ABCD"); + cmd_write_single(X"0000_0120", "1111", X"5500_ABCD"); + cmd_write_single(X"0000_0128", "1111", X"6600_ABCD"); + cmd_write_single(X"0000_0130", "1111", X"7700_ABCD"); + cmd_write_single(X"0000_0138", "1111", X"8800_ABCD"); + cmd_read_single(X"0000_0100"); + cmd_read_single(X"0000_0108"); + cmd_read_single(X"0000_0110"); + cmd_read_single(X"0000_0118"); + cmd_read_single(X"0000_0120"); + cmd_read_single(X"0000_0128"); + cmd_read_single(X"0000_0130"); + cmd_read_single(X"0000_0138"); + cmd_write_single(X"0000_0100", "1111", X"1100_BEEF"); + cmd_read_single(X"0000_0100"); + cmd_write_single(X"0000_0108", "1111", X"2200_BEEF"); + cmd_read_single(X"0000_0108"); + cmd_write_single(X"0000_0110", "1111", X"3300_BEEF"); + cmd_read_single(X"0000_0110"); + cmd_write_single(X"0000_0118", "1111", X"4400_BEEF"); + cmd_read_single(X"0000_0118"); + cmd_write_single(X"0000_0120", "1111", X"5500_BEEF"); + cmd_read_single(X"0000_0120"); + cmd_write_single(X"0000_0128", "1111", X"6600_BEEF"); + cmd_read_single(X"0000_0128"); + cmd_write_single(X"0000_0130", "1111", X"7700_BEEF"); + cmd_read_single(X"0000_0130"); + cmd_write_single(X"0000_0138", "1111", X"8800_BEEF"); + cmd_read_single(X"0000_0138"); + cmd_cycle_en <= '0'; + + wait until rising_edge(clk) and cmd_cycle_finished = '1'; + wait for 60*CLK_PERIOD; + wait until rising_edge(clk); + + end loop; + + state <= IDLE; + + wait; + + end process; + +END;