最近玩了一下xilinx的zynq7000系列,用的是黑金的一款开发板,主要是用来测试一款ADC。在PL部分做了接口逻辑,其中用到了FIFO做数据缓冲,而zynq的PS与PL之间是AXI接口,于是乎问题来了: FIFO写入部分是自定义逻辑,而FIFO读出则是用AXI lite接口,google了一下,没找到相关参考。自动搞了一下,测试可行,记录如下:
PS: ARM + FPGA 是自己比较喜欢的一种架构,用起来比较灵活,以前一直用altera的,现在用了一下xilinx的vivado环境,感觉还不错,就是速度慢点。
------FIFO IP核
component fifo_generator_0 is
PORT (
clk : IN STD_LOGIC;
srst : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
full : OUT STD_LOGIC;
almost_full : OUT STD_LOGIC;
empty : OUT STD_LOGIC;
prog_full : OUT STD_LOGIC
);
end component fifo_generator_0;
begin
--FIFO 例化
fifo_generator_0_inst : fifo_generator_0
port map (
clk => S_AXI_ACLK,
srst => fifo_srst,
din => fifo_wdata,
wr_en => fifo_write,
rd_en => fifo_read,
dout => fifo_rdata,
full => fifo_full,
almost_full => fifo_almost_full,
empty => fifo_empty,
prog_full => fifo_prog_full
);
fifo_srst <= slv_reg0(C_S_AXI_DATA_WIDTH-5);
fifo_wdata <= ads127l01_do;
----------------------------------------------------------------------------------------
fifo_write <= ads127l01_wro_s0 and ads127l01_wro_s1;
process (S_AXI_ACLK)
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
ads127l01_wro_s0 <= '0';
ads127l01_wro_s1 <= '0';
else
ads127l01_wro_s0 <= ads127l01_wro;
ads127l01_wro_s1 <= not ads127l01_wro_s0;
end if;
end if;
end process;
-- fifo write signal generate
-- process (S_AXI_ACLK)
-- variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
-- begin
-- if rising_edge(S_AXI_ACLK) then
-- if S_AXI_ARESETN = '0' then
-- fifo_write <= '0';
-- else
-- loc_addr := axi_awaddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
-- if (slv_reg_wren = '1') then
-- case loc_addr is
-- when b"11" => fifo_write <= '1';
-- when others => fifo_write <= '0';
-- end case;
-- else
-- fifo_write <= '0';
-- end if;
-- end if;
-- end if;
-- end process;
-- fifo read signal generate
process( S_AXI_ACLK ) is
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
if (rising_edge (S_AXI_ACLK)) then
if ( S_AXI_ARESETN = '0' ) then
fifo_read <= '0';
else
loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
if (slv_reg_rden = '1') then
case loc_addr is
when b"10" =>
fifo_read <= '1';
when others =>
fifo_read <= '0';
end case;
else
fifo_read <= '0';
end if;
end if;
end if;
end process;