-- -- read/write bus controller -- -- lb_ signals are computer port -- synchronous, runs at g_clk rate (53MHz) -- -- bp_ signals control backplane at 53MHz/7 rate -- -- register map: -- Offset 0 (15:0) address latch (R/W) -- Offset 1 (15:0) data latch (R/W) -- Offset 2 (1:0) CSR bit 1 - write '1' to trigger bus read -- bit 0 - '1' if DTACK did not occur after timeout -- -- Slot simulation latch is accessed by writing with addr(15:10) = "11110" -- (slot 30) -- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.std_logic_unsigned.all; library dsat_lib; use dsat_lib.dsat.all; entity rwbus is port ( g_clk, g_rst : in std_logic; -- Local bus signals lb_data_in : in std_logic_vector(7 downto 0); -- data in lb_data_out : out std_logic_vector(7 downto 0); -- data out lb_addr : in std_logic_vector(1 downto 0); -- latched address (low bits) lb_ena : in std_logic; -- address match lb_byte : in std_logic_vector(1 downto 0); -- byte counter for word access lb_read : in std_logic; -- local bus read enable lb_write : in std_logic; -- local bus write enable debug : out std_logic_vector(3 downto 0); -- backplane signals bp_d : inout std_logic_vector(15 downto 0); -- backplane data I/O bp_a : out std_logic_vector(15 downto 0); bp_wr, bp_as : out std_logic; bp_clk : out std_logic; bp_den_n, bp_dout : out std_logic; bp_dtack : in std_logic; bp_slot : out std_logic; -- clock for slot simulation latch bp_start : out std_logic); end rwbus; architecture rwbus_a of rwbus is signal addr, data, rd_data : std_logic_vector(15 downto 0); signal bp_d_out : std_logic_vector(15 downto 0); signal bp_clk_s : std_logic; -- backplane clock signal signal bp_clk_cnt : std_logic_vector(2 downto 0); -- backplane clock counter signal bp_read_req, bp_write_req : std_logic; -- read, write request from lb signal bp_read, bp_write : std_logic; -- synchronized read/write request signal bp_read_d0, bp_read_d1 : std_logic; signal bp_as_s : std_logic; signal bp_dtack_s, no_dtack : std_logic; signal bp_dtack_timeout : std_logic_vector(2 downto 0); signal bus_trst : std_logic; signal bp_den_s, bp_dout_s : std_logic; signal bp_slot_d : std_logic; signal init_slot : std_logic_vector(1 downto 0); attribute INIT : string; attribute INIT of bp_slot : signal is "R"; attribute INIT of bp_slot_d : signal is "R"; attribute INIT of bp_dout_s : signal is "R"; attribute INIT of bp_den_s : signal is "S"; begin -- rwbus_a -- this is to set initial slot number to "000000" i_init_slot: srlc16e generic map( INIT => x"ff06") port map( d => '0', clk => g_clk, ce => '1', a0 => '1', a1 => '1', a2 => '1', a3 => '0', q => init_slot(0), q15 => init_slot(1)); -- synchronous logic -- process (g_clk, g_rst) begin -- process if g_rst = '0' then -- asynchronous reset (active low) bp_clk_cnt <= "000"; bp_write <= '0'; bp_read <= '0'; bp_read_req <= '0'; bp_write_req <= '0'; no_dtack <= '0'; bp_as_s <= '0'; bp_den_s <= '1'; bp_dout_s <= '0'; bp_wr <= '0'; bp_slot_d <= '0'; bp_slot <= '0'; bp_d_out <= (others => '0'); -- this is to set initial slot number to "000000" bp_dtack_timeout <= (others => '0'); -- zero DTACK timeout count bp_read_d0 <= '0'; bp_read_d1 <= '0'; elsif g_clk'event and g_clk = '1' then -- rising clock edge ------------------------------------------------------------------------------- -- backplane clock zone (g_clk/7) -- clock output rising edge on phase 0, falling edge on phase 3 -- backplane buffers enable on phase 5, disable on phase 1 -- address, read, write, data out update on phase 2 -- data in, DTACK sampled on phase 0 ------------------------------------------------------------------------------- if init_slot(1) = '1' then bp_clk_cnt <= "000"; else bp_clk_cnt <= bp_clk_cnt + 1; end if; -- phase 0, wrap counter to 000, bp_clk rising edge if bp_clk_cnt = "110" then -- wrap at 7 clocks bp_start <= '0'; bp_clk_cnt <= "000"; bp_dtack_s <= bp_dtack; -- sample dtack on rising edge -- synchronize read/write requests bp_read_d0 <= bp_read; -- delay read for data latch bp_read_d1 <= bp_read_d0; bp_read <= bp_read_req; bp_write <= bp_write_req; if bp_read_req = '1' then bp_dtack_timeout <= (others => '0'); -- zero DTACK timeout count end if; if bp_read = '1' then bp_read_req <= '0'; bp_read <= '0'; end if; if bp_write = '1' then bp_write_req <= '0'; end if; end if; -- phase 3 if bp_clk_cnt = "010" then bp_clk_s <= '0'; -- BPCLK falling edge bp_den_s <= '0'; -- enable backplane buffers end if; -- phase 1, update output signals if bp_clk_cnt = "000" then -- one tick after rising edge bp_den_s <= '1'; -- buffer enable goes off bp_slot_d <= '0'; bp_slot <= bp_slot_d or init_slot(0); bp_wr <= '0'; bp_as_s <= '0'; -- backplane read underway? if bp_read = '1' then bp_dout_s <= '0'; -- set buffers for input bp_as_s <= '1'; -- set AS high end if; if bp_read_d1 = '1' then -- next cycle after read data <= rd_data; -- copy captured data no_dtack <= '0'; end if; -- backplane write underway? if bp_write = '1' then bp_as_s <= '1'; -- writes to bogus slot 30 cause a write to the slot select jumper if addr(15 downto 10) = "111110" then bp_slot_d <= '1'; else bp_wr <= '1'; end if; bp_dout_s <= '1'; end if; if bp_as_s = '1' then -- don't support "block" writes bp_as_s <= '0'; bp_wr <= '0'; bp_dout_s <= '0'; end if; end if; -- phase 5 if bp_clk_cnt = "100" then -- bp_den_s <= '0'; end if; -- phase 6 if bp_clk_cnt = "101" then bp_start <= '1'; bp_clk_s <= '1'; rd_data <= bp_d; -- sample data on rising edge end if; ------------------------------------------------------------------------------- -- local bus zone (g_clk) ------------------------------------------------------------------------------- -- local bus operations if lb_ena = '1' then -- local bus read if lb_read = '1' then if lb_addr = "00" then -- local bus address register read if lb_byte = "00" then lb_data_out <= addr(7 downto 0); elsif lb_byte = "01" then lb_data_out <= addr(15 downto 8); else lb_data_out <= (others => '0'); end if; end if; if lb_addr = "01" then -- local bus data register read if lb_byte = "00" then lb_data_out <= data(7 downto 0); elsif lb_byte = "01" then lb_data_out <= data(15 downto 8); else lb_data_out <= (others => '0'); end if; end if; if lb_addr = "10" then -- CSR read lb_data_out <= "0000000" & no_dtack; end if; end if; -- local bus write if lb_write = '1' then if lb_addr = "00" then -- local bus address register write if lb_byte = "00" then addr(7 downto 0) <= lb_data_in; elsif lb_byte = "01" then addr(15 downto 8) <= lb_data_in; end if; end if; if lb_addr = "01" then -- local bus data register write if lb_byte = "00" then bp_d_out(7 downto 0) <= lb_data_in; data(7 downto 0) <= lb_data_in; elsif lb_byte = "01" then bp_d_out(15 downto 8) <= lb_data_in; data(15 downto 8) <= lb_data_in; bp_write_req <= '1'; -- start backplane write cycle end if; -- (no action on bytes 2, 3 unless programming FPGA) if addr(9 downto 2) = "00000001" then if lb_byte = "10" then bp_d_out(7 downto 0) <= lb_data_in; data(7 downto 0) <= lb_data_in; elsif lb_byte = "11" then bp_d_out(15 downto 8) <= lb_data_in; data(15 downto 8) <= lb_data_in; bp_write_req <= '1'; -- start backplane write cycle end if; end if; end if; if lb_addr = "10" then -- CSR write if lb_byte = "00" and lb_data_in(1) = '1' then bp_read_req <= '1'; -- start backplane read cycle end if; end if; end if; end if; end if; end process; -- asynchronous logic bp_clk <= bp_clk_s; bp_as <= bp_as_s; -- changed to move the registers to IOB -- bp_d_out <= data; bp_a <= addr; bp_den_n <= bp_den_s; bp_dout <= bp_dout_s; debug(0) <= bp_den_s; debug(1) <= bp_dout_s; bus_trst <= (bp_den_s or not bp_dout_s) and not init_slot(1); bp_d <= bp_d_out when bus_trst = '0' else (others => 'Z'); end rwbus_a;