Aleksei_Rostov 0 20 октября, 2014 Опубликовано 20 октября, 2014 · Жалоба Здравствуйте. Подскажите пожалуйста, как можно правильно подключить VHDL ядро RAM к шине AXI4. Задача: необходимо аппаратное ядро буфер RAM подключить к AXi4 для считывания данных из буфера с помощью microblaze. пока пробую простой вариант для rom. Что делаю: в ISE создаю проект, добавляю mblz. Открываю XPS и там создаю новое ядро. Есть два файла: user_logic.vhdl и топовый файл ядра. В user_logic.vhd добавляю rom. En на считывание завожу на статусный регистр считывания данных из IP ядра (slv_reg_read_sel = "0100"). Далее в SDK пытаюсь считать из регистра содержимое rom. user_logic код library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library proc_common_v3_00_a; use proc_common_v3_00_a.proc_common_pkg.all; -- DO NOT EDIT ABOVE THIS LINE -------------------- --USER libraries added here ------------------------------------------------------------------------------ -- Entity section ------------------------------------------------------------------------------ -- Definition of Generics: -- C_NUM_REG -- Number of software accessible registers -- C_SLV_DWIDTH -- Slave interface data bus width -- -- Definition of Ports: -- Bus2IP_Clk -- Bus to IP clock -- Bus2IP_Resetn -- Bus to IP reset -- Bus2IP_Data -- Bus to IP data bus -- Bus2IP_BE -- Bus to IP byte enables -- Bus2IP_RdCE -- Bus to IP read chip enable -- Bus2IP_WrCE -- Bus to IP write chip enable -- IP2Bus_Data -- IP to Bus data bus -- IP2Bus_RdAck -- IP to Bus read transfer acknowledgement -- IP2Bus_WrAck -- IP to Bus write transfer acknowledgement -- IP2Bus_Error -- IP to Bus error response ------------------------------------------------------------------------------ entity user_logic is generic ( -- ADD USER GENERICS BELOW THIS LINE --------------- --USER generics added here -- ADD USER GENERICS ABOVE THIS LINE --------------- -- DO NOT EDIT BELOW THIS LINE --------------------- -- Bus protocol parameters, do not add to or delete C_NUM_REG : integer := 4; C_SLV_DWIDTH : integer := 32 -- DO NOT EDIT ABOVE THIS LINE --------------------- ); port ( -- ADD USER PORTS BELOW THIS LINE ------------------ --USER ports added here LEDS_OUT : out std_logic_vector(7 downto 0); DATA_OUT : out std_logic_vector(7 downto 0); RDEN : out std_logic; EOF_P : out std_logic; -- ADD USER PORTS ABOVE THIS LINE ------------------ -- DO NOT EDIT BELOW THIS LINE --------------------- -- Bus protocol ports, do not add to or delete Bus2IP_Clk : in std_logic; Bus2IP_Resetn : in std_logic; Bus2IP_Data : in std_logic_vector(C_SLV_DWIDTH-1 downto 0); Bus2IP_BE : in std_logic_vector(C_SLV_DWIDTH/8-1 downto 0); Bus2IP_RdCE : in std_logic_vector(C_NUM_REG-1 downto 0); Bus2IP_WrCE : in std_logic_vector(C_NUM_REG-1 downto 0); IP2Bus_Data : out std_logic_vector(C_SLV_DWIDTH-1 downto 0); IP2Bus_RdAck : out std_logic; IP2Bus_WrAck : out std_logic; IP2Bus_Error : out std_logic -- DO NOT EDIT ABOVE THIS LINE --------------------- ); attribute MAX_FANOUT : string; attribute SIGIS : string; attribute SIGIS of Bus2IP_Clk : signal is "CLK"; attribute SIGIS of Bus2IP_Resetn : signal is "RST"; end entity user_logic; ------------------------------------------------------------------------------ -- Architecture section ------------------------------------------------------------------------------ architecture IMP of user_logic is --USER signal declarations added here, as needed for user logic type rom_type is array (15 downto 0) of std_logic_vector (7 downto 0); signal ROM_arr : rom_type:= (X"01", X"10", X"02", X"20", X"03", X"30", X"04", X"40", X"05", X"50", X"06", X"60", X"07", X"70", X"08", X"80"); signal rdata : std_logic_vector(7 downto 0); signal ADDR : std_logic_vector(3 downto 0); signal SWITCH_IN : std_logic_vector(7 downto 0); signal RD_EN, EOF : std_logic; ------------------------------------------ -- Signals for user logic slave model s/w accessible register example ------------------------------------------ signal slv_reg0 : std_logic_vector(C_SLV_DWIDTH-1 downto 0); signal slv_reg1 : std_logic_vector(C_SLV_DWIDTH-1 downto 0); signal slv_reg2 : std_logic_vector(C_SLV_DWIDTH-1 downto 0); signal slv_reg3 : std_logic_vector(C_SLV_DWIDTH-1 downto 0); signal slv_reg_write_sel : std_logic_vector(3 downto 0); signal slv_reg_read_sel : std_logic_vector(3 downto 0); signal slv_ip2bus_data : std_logic_vector(C_SLV_DWIDTH-1 downto 0); signal slv_read_ack : std_logic; signal slv_write_ack : std_logic; begin -- сигналы для контроля в chipscope DATA_OUT <= SWITCH_IN; RDEN <= RD_EN; EOF_P <= EOF; rdata <= ROM_arr(conv_integer(ADDR)); process (Bus2IP_Clk) begin if (Bus2IP_Clk'event and Bus2IP_Clk = '1') then if (RD_EN = '1') then SWITCH_IN <= rdata; ADDR <= ADDR + 1; else ADDR <= (others => '0'); end if; end if; end process; EOF <= '1' when ADDR = x"E" else '0'; ------------------------------------------ -- Example code to read/write user logic slave model s/w accessible registers -- -- Note: -- The example code presented here is to show you one way of reading/writing -- software accessible registers implemented in the user logic slave model. -- Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond -- to one software accessible register by the top level template. For example, -- if you have four 32 bit software accessible registers in the user logic, -- you are basically operating on the following memory mapped registers: -- -- Bus2IP_WrCE/Bus2IP_RdCE Memory Mapped Register -- "1000" C_BASEADDR + 0x0 -- "0100" C_BASEADDR + 0x4 -- "0010" C_BASEADDR + 0x8 -- "0001" C_BASEADDR + 0xC -- ------------------------------------------ slv_reg_write_sel <= Bus2IP_WrCE(3 downto 0); slv_reg_read_sel <= Bus2IP_RdCE(3 downto 0); slv_write_ack <= Bus2IP_WrCE(0) or Bus2IP_WrCE(1) or Bus2IP_WrCE(2) or Bus2IP_WrCE(3); slv_read_ack <= Bus2IP_RdCE(0) or Bus2IP_RdCE(1) or Bus2IP_RdCE(2) or Bus2IP_RdCE(3); -- implement slave model software accessible register(s) SLAVE_REG_WRITE_PROC : process( Bus2IP_Clk ) is begin if Bus2IP_Clk'event and Bus2IP_Clk = '1' then if Bus2IP_Resetn = '0' then slv_reg0 <= (others => '0'); slv_reg1 <= (others => '0'); slv_reg2 <= (others => '0'); slv_reg3 <= (others => '0'); else case slv_reg_write_sel is when "1000" => for byte_index in 0 to (C_SLV_DWIDTH/8)-1 loop if ( Bus2IP_BE(byte_index) = '1' ) then slv_reg0(byte_index*8+7 downto byte_index*8) <= Bus2IP_Data(byte_index*8+7 downto byte_index*8); end if; end loop; when "0100" => for byte_index in 0 to (C_SLV_DWIDTH/8)-1 loop if ( Bus2IP_BE(byte_index) = '1' ) then slv_reg1(byte_index*8+7 downto byte_index*8) <= Bus2IP_Data(byte_index*8+7 downto byte_index*8); end if; end loop; when "0010" => for byte_index in 0 to (C_SLV_DWIDTH/8)-1 loop if ( Bus2IP_BE(byte_index) = '1' ) then slv_reg2(byte_index*8+7 downto byte_index*8) <= Bus2IP_Data(byte_index*8+7 downto byte_index*8); end if; end loop; when "0001" => for byte_index in 0 to (C_SLV_DWIDTH/8)-1 loop if ( Bus2IP_BE(byte_index) = '1' ) then slv_reg3(byte_index*8+7 downto byte_index*8) <= Bus2IP_Data(byte_index*8+7 downto byte_index*8); end if; end loop; when others => null; end case; end if; end if; end process SLAVE_REG_WRITE_PROC; -- implement slave model software accessible register(s) read mux SLAVE_REG_READ_PROC : process( slv_reg_read_sel, slv_reg0, slv_reg1, slv_reg2, slv_reg3 ) is begin case slv_reg_read_sel is when "1000" => slv_ip2bus_data <= slv_reg0; when "0100" => slv_ip2bus_data <= x"000000" & SWITCH_IN; when "0010" => slv_ip2bus_data <= x"0000000" & "000" & EOF; when "0001" => slv_ip2bus_data <= slv_reg3; when others => slv_ip2bus_data <= (others => '0'); end case; end process SLAVE_REG_READ_PROC; ------------------------------------------ -- Example code to drive IP to Bus signals ------------------------------------------ IP2Bus_Data <= slv_ip2bus_data when slv_read_ack = '1' else (others => '0'); IP2Bus_WrAck <= slv_write_ack; IP2Bus_RdAck <= slv_read_ack; IP2Bus_Error <= '0'; LEDS_OUT <= slv_reg0(7 downto 0); RD_EN <= '1' when slv_reg_read_sel = "0100" else '0'; end IMP; и собственно код в SDK int main() { u8 sw[16]; while(1){ for(i = 0; i <= 15; i++) { sw[i] = Xil_In8(MY_CORE_REG_BASEADDR + 0x04);// +0x04 т.к. slv_reg_read_sel = "0100" } } return 0; } Если я правильно понимаю, то пока работает Xil_In8, то slv_reg_read_sel = "0100" и следовательно моя rom считывается. Но chipscopom вижу что это не так. Какие есть еще варианты реализации? В Altere я просто создавал ram HDL файл, одни ноги из которого шли на шину (типа read_en, addr, data), а другие снаружу в аппаратную часть (wr_en, addr, data). Создавал ядро. Далее в Eclipse ставил указатель на base addr ядра и вычитывал данные с адр пространства. Посоветуйте пожалуйста как лучше сделать в Xilinx. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 20 октября, 2014 Опубликовано 20 октября, 2014 · Жалоба В ксалинксе надо в платформ студии нажать вкладку создания и импорт модулей. Нажать создать новый регистровый модуль, пометить галкой вместе с проектом ISE. В ISE открыть созданный проект, и в user.vhdl у вас будет шаблон чтения и записи в регистры по адресам. ну дальше все переписать под себя сбилдить модуль, и импортировать его обратно в платформ студию, подключить к микроблайзу и обращаться к ядру через адреса. судя по тексту выше вы примерно это и получили, тогда остается понять логику внутри, правильная ли она кстати что такое Xil_In8 ? все что висит на шине доступно просто через int *data = (int *)(MY_CORE_REG_BASEADDR + 0x04); *data = 5; //записать int temp = *data; //считать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться