library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; -- lx_rocon_top - wires the modules with outside world -- ====================================================== -- INTERNAL MEMORY BUS -- ====================================================== -- -- Internal memory bus has the following wires: -- -- - address[15..0] The address -- - data_in[31..0] The data coming to bus -- - data_out[31..0] The data coming from bus, multiplexed -- - rd Read enable, active LOW -- - bls[3..0] Write enable for respective bytes, active LOW -- In some cases, only WR is used -- - ta Transaction acknowledge (latches data out), active LOW, multiplexed entity lx_rocon_top is port ( -- External clk_cpu : in std_logic; cs0_xc : in std_logic; rd : in std_logic; bls : in std_logic_vector(3 downto 0); address : in std_logic_vector(15 downto 0); data : inout std_logic_vector(31 downto 0); irc1_a : in std_logic; irc1_b : in std_logic; irc1_index : in std_logic; irc1_mark : in std_logic; irc2_a : in std_logic; irc2_b : in std_logic; irc2_index : in std_logic; irc2_mark : in std_logic; irc3_a : in std_logic; irc3_b : in std_logic; irc3_index : in std_logic; irc3_mark : in std_logic; irc4_a : in std_logic; irc4_b : in std_logic; irc4_index : in std_logic; irc4_mark : in std_logic; init : in std_logic ); end lx_rocon_top; architecture Behavioral of lx_rocon_top is -- Reset signal signal reset : std_logic; -- Peripherals on the memory bus signal bram_out : std_logic_vector(31 downto 0); signal bram_ta : std_logic; signal bram_ce : std_logic; signal irc_reg_out : std_logic_vector(31 downto 0); signal irc_reg_ta : std_logic; signal irc_reg_ce : std_logic; signal bcd_out : std_logic_vector(31 downto 0); signal bcd_ta : std_logic; signal bcd_ce : std_logic; signal id1_reg_out : std_logic_vector(31 downto 0); signal id1_reg_ta : std_logic; signal id1_reg_ce : std_logic; signal id2_reg_out : std_logic_vector(31 downto 0); signal id2_reg_ta : std_logic; signal id2_reg_ce : std_logic; -- Signals for external bus transmission signal data_in_bus : std_logic_vector(31 downto 0); signal data_out_bus : std_logic_vector(31 downto 0); -- Signals for internal transaction signal last_address : std_logic_vector(15 downto 0); signal last_rd : std_logic; signal last_bls : std_logic_vector(3 downto 0); -- Reading logic: -- Broadcast rd only till ta (transaction acknowledge) -- is received, then latch the data till the state of -- rd or address changes signal i_ta : std_logic; signal i_rd : std_logic; signal data_read : std_logic_vector(31 downto 0); signal acked : std_logic; -- Writing logic: signal i_bls : std_logic_vector(3 downto 0); signal data_write : std_logic_vector(31 downto 0); component bus_irc port ( clk : in std_logic; reset : in std_logic; address : in std_logic_vector(3 downto 0); ce : in std_logic; data_in : in std_logic; data_out : out std_logic_vector(31 downto 0); rd : in std_logic; wr : in std_logic; ta : out std_logic; irc1_a : in std_logic; irc1_b : in std_logic; irc1_index : in std_logic; irc1_mark : in std_logic; irc2_a : in std_logic; irc2_b : in std_logic; irc2_index : in std_logic; irc2_mark : in std_logic; irc3_a : in std_logic; irc3_b : in std_logic; irc3_index : in std_logic; irc3_mark : in std_logic; irc4_a : in std_logic; irc4_b : in std_logic; irc4_index : in std_logic; irc4_mark : in std_logic ); end component; component bus_control_bram port ( clk : in std_logic; ena : in std_logic; wea : in std_logic_vector(3 downto 0); addra : in std_logic_vector(8 downto 0); dina : in std_logic_vector(31 downto 0); douta : out std_logic_vector(31 downto 0); taa : out std_logic; enb : in std_logic; web : in std_logic_vector(3 downto 0); addrb : in std_logic_vector(8 downto 0); dinb : in std_logic_vector(31 downto 0); doutb : out std_logic_vector(31 downto 0) ); end component; component bus_bcd port ( reset : in std_logic; en : in std_logic; clk : in std_logic; ce : in std_logic; data_out : out std_logic_vector(31 downto 0); rd : in std_logic; ta : out std_logic ); end component; component bus_id generic ( id : std_logic_vector(31 downto 0) ); port ( ce : in std_logic; data_out : out std_logic_vector(31 downto 0); rd : in std_logic; ta : out std_logic ); end component; begin -- IRC interconnect memory_bus_irc: bus_irc port map ( clk => clk_cpu, reset => reset, address => address(3 downto 0), ce => irc_reg_ce, data_in => data_in_bus(0), data_out => irc_reg_out, rd => i_rd, wr => bls(0), ta => irc_reg_ta, irc1_a => irc1_a, irc1_b => irc1_b, irc1_index => irc1_index, irc1_mark => irc1_mark, irc2_a => irc2_a, irc2_b => irc2_b, irc2_index => irc2_index, irc2_mark => irc2_mark, irc3_a => irc3_a, irc3_b => irc3_b, irc3_index => irc3_index, irc3_mark => irc3_mark, irc4_a => irc4_a, irc4_b => irc4_b, irc4_index => irc4_index, irc4_mark => irc4_mark ); -- Control BRAM interconnect (9 kib) memory_bus_control_bram: bus_control_bram port map ( clk => clk_cpu, ena => bram_ce, taa => bram_ta, wea => i_bls, addra => address(8 downto 0), dina => data_in_bus, douta => bram_out, enb => '0', web => (others => '0'), addrb => (others => '0'), dinb => (others => '0'), doutb => open ); -- BCD memory_bus_bcd: bus_bcd port map ( reset => reset, en => '0', clk => clk_cpu, ce => bcd_ce, rd => i_rd, ta => bcd_ta, data_out => bcd_out ); -- ID1 register (=0xBOOBBABE) memory_bus_id1: bus_id generic map ( id => "10110000000010111011101010111110" ) port map ( ce => id1_reg_ce, rd => i_rd, ta => id1_reg_ta, data_out => id1_reg_out ); -- ID2 register (=0xDEADBEEF) memory_bus_id2: bus_id generic map ( id => "11011110101011011011111011101111" ) port map ( ce => id2_reg_ce, rd => i_rd, ta => id2_reg_ta, data_out => id2_reg_out ); -- Bus update memory_bus_update: process(clk_cpu) begin if clk_cpu = '1' and clk_cpu'event then -- Set every signal to inactive state here irc_reg_ce <= '1'; bram_ce <= '1'; bcd_ce <= '1'; id1_reg_ce <= '1'; id2_reg_ce <= '1'; i_rd <= '1'; i_bls <= (others => '1'); data_in_bus <= (others => '1'); -- Check if we have chip select if cs0_xc = '0' then -- Memory Map (16-bit address @ 32-bit each) -- Each address is seen as 32-bit entry now -- 0x0000 - 0x011F: Control dual-port BRAM -- 0x8000 - 0x800F: IRC registers -- 0xFFFD: 32-bit BCD -- 0xFFFE: ID1 register -- 0xFFFF: ID2 register if address < "0000000100100000" then -- Control BRAM bram_ce <= '0'; i_ta <= bram_ta; data_out_bus <= bram_out; elsif address(15 downto 4) = "100000000000" then -- IRC irc_reg_ce <= '0'; i_ta <= irc_reg_ta; data_out_bus <= irc_reg_out; elsif address = "1111111111111101" then -- BCD bcd_ce <= '0'; i_ta <= bcd_ta; data_out_bus <= bcd_out; elsif address = "1111111111111110" then -- ID1 id1_reg_ce <= '0'; i_ta <= id1_reg_ta; data_out_bus <= id1_reg_out; elsif address = "1111111111111111" then -- ID2 id2_reg_ce <= '0'; i_ta <= id2_reg_ta; data_out_bus <= id2_reg_out; end if; -- Reading if rd = '0' then if last_rd = '1' or last_address /= address then -- Getting something new -- Set internal RD to active and reset ack and latched data acked <= '0'; i_rd <= '0'; -- Data latching - synchronous data_read <= (others => 'X'); elsif i_rd = '0' and acked = '0' and i_ta = '0' then -- Got acknowledge, latch data acked <= '1'; data_read <= data_out_bus; elsif acked = '0' then -- Ongoing read, keep the signal low i_rd <= '0'; data_read <= (others => 'X'); end if; last_address <= address; else -- Not reading, anything goes data_read <= (others => 'X'); end if; last_rd <= rd; -- Writing if bls /= "1111" then if last_bls /= bls or last_address /= address then -- Data are valid when BLS is active, broadcast it for one cycle i_bls <= bls; data_in_bus <= data_write; end if; last_address <= address; end if; last_bls <= bls; else -- Set last read / bls to '1' if CS0 is not asserted last_rd <= '1'; last_bls <= (others => '1'); end if; end if; end process; -- If RD and BLS is not high, we must keep DATA at high impedance -- or the FPGA collides with SDRAM (burning each other) memory_bus_out: process(cs0_xc, rd, data, data_read) begin -- CS0 / RD / BLS are active LOW if cs0_xc = '0' and rd = '0' then data <= data_read; else -- IMPORTANT!!! data <= (others => 'Z'); end if; data_write <= data; end process; -- Reset initialization: process(init) begin reset <= init; end process; end Behavioral;