URL
https://opencores.org/ocsvn/pcie_sg_dma/pcie_sg_dma/trunk
Subversion Repositories pcie_sg_dma
[/] [pcie_sg_dma/] [branches/] [Virtex6/] [ML605_ISE13.3/] [ipcore_dir_ISE13.3/] [v6_pcie_v1_7_x1/] [example_design/] [PIO_EP_MEM_ACCESS.vhd] - Rev 13
Compare with Previous | Blame | View Log
------------------------------------------------------------------------------- -- -- (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved. -- -- This file contains confidential and proprietary information -- of Xilinx, Inc. and is protected under U.S. and -- international copyright and other intellectual property -- laws. -- -- DISCLAIMER -- This disclaimer is not a license and does not grant any -- rights to the materials distributed herewith. Except as -- otherwise provided in a valid license issued to you by -- Xilinx, and to the maximum extent permitted by applicable -- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND -- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES -- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING -- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- -- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and -- (2) Xilinx shall not be liable (whether in contract or tort, -- including negligence, or under any other theory of -- liability) for any loss or damage of any kind or nature -- related to, arising under or in connection with these -- materials, including for any direct, or any indirect, -- special, incidental, or consequential loss or damage -- (including loss of data, profits, goodwill, or any type of -- loss or damage suffered as a result of any action brought -- by a third party) even if such damage or loss was -- reasonably foreseeable or Xilinx had been advised of the -- possibility of the same. -- -- CRITICAL APPLICATIONS -- Xilinx products are not designed or intended to be fail- -- safe, or for use in any application requiring fail-safe -- performance, such as life-support or safety devices or -- systems, Class III medical devices, nuclear facilities, -- applications related to the deployment of airbags, or any -- other applications that could lead to death, personal -- injury, or severe property or environmental damage -- (individually and collectively, "Critical -- Applications"). Customer assumes the sole risk and -- liability of any use of Xilinx products in Critical -- Applications, subject only to applicable laws and -- regulations governing limitations on product liability. -- -- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS -- PART OF THIS FILE AT ALL TIMES. -- ------------------------------------------------------------------------------- -- Project : Virtex-6 Integrated Block for PCI Express -- File : PIO_EP_MEM_ACCESS.vhd -- Version : 1.7 ---- ---- Description: Endpoint Memory Access Unit. This module provides access functions ---- to the Endpoint memory aperture. ---- ---- Read Access: Module returns data for the specifed address and ---- byte enables selected. ---- ---- Write Access: Module accepts data and byte enables and updates ---- data when write enable is asserted. Modules signals write busy ---- write is in progress. ---- ---------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; entity PIO_EP_MEM_ACCESS is port ( clk : in std_logic; rst_n : in std_logic; -- Read Port rd_addr_i : in std_logic_vector(10 downto 0); rd_be_i : in std_logic_vector(3 downto 0); rd_data_o : out std_logic_vector(31 downto 0); -- Write Port wr_addr_i : in std_logic_vector(10 downto 0); wr_be_i : in std_logic_vector(7 downto 0); wr_data_i : in std_logic_vector(31 downto 0); wr_en_i : in std_logic; wr_busy_o : out std_logic ); end PIO_EP_MEM_ACCESS; architecture rtl of PIO_EP_MEM_ACCESS is type state_type is (PIO_MEM_ACCESS_WR_RST, PIO_MEM_ACCESS_WR_READ, PIO_MEM_ACCESS_WR_WRITE ); component EP_MEM port ( clk_i : in std_logic ; a_rd_a_i_0 : in std_logic_vector(8 downto 0); a_rd_d_o_0 : out std_logic_vector(31 downto 0); a_rd_en_i_0 : in std_logic ; b_wr_a_i_0 : in std_logic_vector(8 downto 0); b_wr_d_i_0 : in std_logic_vector(31 downto 0); b_wr_en_i_0 : in std_logic ; b_rd_d_o_0 : out std_logic_vector(31 downto 0); b_rd_en_i_0 : in std_logic ; a_rd_a_i_1 : in std_logic_vector(8 downto 0); a_rd_d_o_1 : out std_logic_vector(31 downto 0); a_rd_en_i_1 : in std_logic ; b_wr_a_i_1 : in std_logic_vector(8 downto 0); b_wr_d_i_1 : in std_logic_vector(31 downto 0); b_wr_en_i_1 : in std_logic ; b_rd_d_o_1 : out std_logic_vector(31 downto 0); b_rd_en_i_1 : in std_logic ; a_rd_a_i_2 : in std_logic_vector(8 downto 0); a_rd_d_o_2 : out std_logic_vector(31 downto 0); a_rd_en_i_2 : in std_logic ; b_wr_a_i_2 : in std_logic_vector(8 downto 0); b_wr_d_i_2 : in std_logic_vector(31 downto 0); b_wr_en_i_2 : in std_logic ; b_rd_d_o_2 : out std_logic_vector(31 downto 0); b_rd_en_i_2 : in std_logic ; a_rd_a_i_3 : in std_logic_vector(8 downto 0); a_rd_d_o_3 : out std_logic_vector(31 downto 0); a_rd_en_i_3 : in std_logic ; b_wr_a_i_3 : in std_logic_vector(8 downto 0); b_wr_d_i_3 : in std_logic_vector(31 downto 0); b_wr_en_i_3 : in std_logic ; b_rd_d_o_3 : out std_logic_vector(31 downto 0); b_rd_en_i_3 : in std_logic ); end component; signal rd_data0_q : std_logic_vector(31 downto 0); signal rd_data1_q : std_logic_vector(31 downto 0); signal rd_data2_q : std_logic_vector(31 downto 0); signal rd_data3_q : std_logic_vector(31 downto 0); signal rd_data0_o : std_logic_vector(31 downto 0); signal rd_data1_o : std_logic_vector(31 downto 0); signal rd_data2_o : std_logic_vector(31 downto 0); signal rd_data3_o : std_logic_vector(31 downto 0); signal write_en : std_logic; signal post_wr_data : std_logic_vector(31 downto 0); signal w_pre_wr_data : std_logic_vector(31 downto 0); signal wr_mem_state : state_type; signal pre_wr_data : std_logic_vector(31 downto 0); signal w_pre_wr_data0 : std_logic_vector(31 downto 0); signal w_pre_wr_data1 : std_logic_vector(31 downto 0); signal w_pre_wr_data2 : std_logic_vector(31 downto 0); signal w_pre_wr_data3 : std_logic_vector(31 downto 0); signal pre_wr_data0_q, pre_wr_data1_q : std_logic_vector(31 downto 0); signal pre_wr_data2_q, pre_wr_data3_q : std_logic_vector(31 downto 0); signal rd_data_raw_o : std_logic_vector(31 downto 0); -- Memory Write Process -- Extract current data bytes. These need to be swizzled -- BRAM storage format : -- data[31:0] = { byte[3], byte[2], byte[1], byte[0] (lowest addr) } signal w_pre_wr_data_b3 : std_logic_vector(7 downto 0); signal w_pre_wr_data_b2 : std_logic_vector(7 downto 0); signal w_pre_wr_data_b1 : std_logic_vector(7 downto 0); signal w_pre_wr_data_b0 : std_logic_vector(7 downto 0); -- Extract new data bytes from payload -- TLP Payload format : -- data[31:0] = { byte[0] (lowest addr), byte[2], byte[1], byte[3] } signal w_wr_data_b3 : std_logic_vector(7 downto 0); signal w_wr_data_b2 : std_logic_vector(7 downto 0); signal w_wr_data_b1 : std_logic_vector(7 downto 0); signal w_wr_data_b0 : std_logic_vector(7 downto 0); signal w_wr_data0_int : std_logic_vector(7 downto 0); signal w_wr_data1_int : std_logic_vector(7 downto 0); signal w_wr_data2_int : std_logic_vector(7 downto 0); signal w_wr_data3_int : std_logic_vector(7 downto 0); signal rd_data0_en : std_logic; signal rd_data1_en : std_logic; signal rd_data2_en : std_logic; signal rd_data3_en : std_logic; signal interim : std_logic; signal rd_data_raw_int0 : std_logic_vector(7 downto 0); signal rd_data_raw_int1 : std_logic_vector(7 downto 0); signal rd_data_raw_int2 : std_logic_vector(7 downto 0); signal rd_data_raw_int3 : std_logic_vector(7 downto 0); signal b_wr_en_0, b_wr_en_0_int : std_logic; signal b_wr_en_1, b_wr_en_1_int : std_logic; signal b_wr_en_2, b_wr_en_2_int : std_logic; signal b_wr_en_3, b_wr_en_3_int : std_logic; signal wr_addr_0 : std_logic; signal wr_addr_1 : std_logic; signal wr_addr_2 : std_logic; signal wr_addr_3 : std_logic; begin w_wr_data_b3 <= wr_data_i(7 downto 0); w_wr_data_b2 <= wr_data_i(15 downto 8); w_wr_data_b1 <= wr_data_i(23 downto 16); w_wr_data_b0 <= wr_data_i(31 downto 24); w_pre_wr_data_b3 <= pre_wr_data(31 downto 24); w_pre_wr_data_b2 <= pre_wr_data(23 downto 16); w_pre_wr_data_b1 <= pre_wr_data(15 downto 08); w_pre_wr_data_b0 <= pre_wr_data(07 downto 00); w_wr_data3_int <= w_wr_data_b3 when (wr_be_i(3) = '1') else w_pre_wr_data_b3; w_wr_data2_int <= w_wr_data_b2 when (wr_be_i(2) = '1') else w_pre_wr_data_b2; w_wr_data1_int <= w_wr_data_b1 when (wr_be_i(1) = '1') else w_pre_wr_data_b1; w_wr_data0_int <= w_wr_data_b0 when (wr_be_i(0) = '1') else w_pre_wr_data_b0; process(clk, rst_n) begin if ( rst_n = '0' ) then write_en <= '0'; pre_wr_data <= (others => '0'); post_wr_data <= (others => '0'); pre_wr_data <= (others => '0'); pre_wr_data0_q <= (others => '0'); pre_wr_data1_q <= (others => '0'); pre_wr_data2_q <= (others => '0'); pre_wr_data3_q <= (others => '0'); wr_mem_state <= PIO_MEM_ACCESS_WR_RST; else if (clk'event and clk = '1') then case ( wr_mem_state ) is when PIO_MEM_ACCESS_WR_RST => if (wr_en_i = '1') then -- read state -- Pipeline B port data before processing pre_wr_data0_q <= w_pre_wr_data0; pre_wr_data1_q <= w_pre_wr_data1; pre_wr_data2_q <= w_pre_wr_data2; pre_wr_data3_q <= w_pre_wr_data3; write_en <= '0'; wr_mem_state <= PIO_MEM_ACCESS_WR_READ ; else write_en <= '0'; wr_mem_state <= PIO_MEM_ACCESS_WR_RST; end if; when PIO_MEM_ACCESS_WR_READ => -- Now save the selected BRAM B port data out pre_wr_data <= w_pre_wr_data; write_en <= '0'; wr_mem_state <= PIO_MEM_ACCESS_WR_WRITE; when PIO_MEM_ACCESS_WR_WRITE => -- Merge new enabled data and write target BlockRAM location post_wr_data <= w_wr_data3_int & w_wr_data2_int & w_wr_data1_int & w_wr_data0_int; write_en <= '1'; wr_mem_state <= PIO_MEM_ACCESS_WR_RST; when others => null; end case; end if; end if; end process; -- Write controller busy wr_busy_o <= wr_en_i or interim; interim <= '1' when (wr_mem_state /= PIO_MEM_ACCESS_WR_RST) else '0'; -- Select BlockRAM output based on higher 2 address bits process(wr_addr_i, pre_wr_data0_q, pre_wr_data1_q, pre_wr_data2_q, pre_wr_data3_q) begin case (wr_addr_i(10 downto 9)) is when "00" => w_pre_wr_data <= pre_wr_data0_q; when "01" => w_pre_wr_data <= pre_wr_data1_q; when "10" => w_pre_wr_data <= pre_wr_data2_q; when "11" => w_pre_wr_data <= pre_wr_data3_q; when others => null; end case; end process; -- Memory Read Controller rd_data0_en <= '1' when (rd_addr_i(10 downto 9) = "00") else '0'; rd_data1_en <= '1' when (rd_addr_i(10 downto 9) = "01") else '0'; rd_data2_en <= '1' when (rd_addr_i(10 downto 9) = "10") else '0'; rd_data3_en <= '1' when (rd_addr_i(10 downto 9) = "11") else '0'; -- pipeline stage BRAM read data before processing -- process(rst_n, clk) begin if ( rst_n = '0' ) then rd_data0_q <= (others => '0'); rd_data1_q <= (others => '0'); rd_data2_q <= (others => '0'); rd_data3_q <= (others => '0'); else if (clk'event and clk='1') then rd_data0_q <= rd_data0_o(31 downto 0); rd_data1_q <= rd_data1_o(31 downto 0); rd_data2_q <= rd_data2_o(31 downto 0); rd_data3_q <= rd_data3_o(31 downto 0); end if; end if; end process; process(rd_addr_i(10 downto 0), rd_data0_q(31 downto 0), rd_data1_q(31 downto 0), rd_data2_q(31 downto 0), rd_data3_q(31 downto 0)) begin case (rd_addr_i(10 downto 9)) is when "00" => rd_data_raw_o <= rd_data0_q(31 downto 0); when "01" => rd_data_raw_o <= rd_data1_q(31 downto 0); when "10" => rd_data_raw_o <= rd_data2_q(31 downto 0); when "11" => rd_data_raw_o <= rd_data3_q(31 downto 0); when others => null; end case; end process; -- Handle Read byte enables -- rd_data_o <= rd_data_raw_int0 & rd_data_raw_int1 & rd_data_raw_int2 & rd_data_raw_int3 ; rd_data_raw_int0 <= rd_data_raw_o(7 downto 0) when (rd_be_i(0) = '1') else (others => '0'); rd_data_raw_int1 <= rd_data_raw_o(15 downto 8) when (rd_be_i(1) = '1') else (others => '0'); rd_data_raw_int2 <= rd_data_raw_o(23 downto 16) when (rd_be_i(2) = '1') else (others => '0'); rd_data_raw_int3 <= rd_data_raw_o (31 downto 24) when (rd_be_i(3) = '1') else (others => '0'); b_wr_en_0 <= write_en and b_wr_en_0_int; b_wr_en_0_int <= '1' when (wr_addr_i(10 downto 9) = "00") else '0'; b_wr_en_1 <= write_en and b_wr_en_1_int; b_wr_en_1_int <= '1' when (wr_addr_i(10 downto 9) = "01") else '0'; b_wr_en_2 <= write_en and b_wr_en_2_int; b_wr_en_2_int <= '1' when (wr_addr_i(10 downto 9) = "10") else '0'; b_wr_en_3 <= write_en and b_wr_en_3_int; b_wr_en_3_int <= '1' when (wr_addr_i(10 downto 9) = "11") else '0'; wr_addr_0 <= '1' when (wr_addr_i(10 downto 9) = "00") else '0'; wr_addr_1 <= '1' when (wr_addr_i(10 downto 9) = "01") else '0'; wr_addr_2 <= '1' when (wr_addr_i(10 downto 9) = "10") else '0'; wr_addr_3 <= '1' when (wr_addr_i(10 downto 9) = "11") else '0'; EP_MEM_inst : EP_MEM port map ( clk_i => clk, a_rd_a_i_0 => rd_addr_i(8 downto 0), -- I [8:0] a_rd_en_i_0 => rd_data0_en, -- I [1:0] a_rd_d_o_0 => rd_data0_o, -- O [31:0] b_wr_a_i_0 => wr_addr_i(8 downto 0), -- I [8:0] b_wr_d_i_0 => post_wr_data, -- I [31:0] b_wr_en_i_0 => b_wr_en_0, --{write_en & (wr_addr_i[10:9] == 2'b00)}), -- I b_rd_d_o_0 => w_pre_wr_data0(31 downto 0), -- O [31:0] b_rd_en_i_0 => wr_addr_0, --{wr_addr_i[10:9] == 2'b00}), -- I a_rd_a_i_1 => rd_addr_i(8 downto 0), -- I [8:0] a_rd_en_i_1 => rd_data1_en, -- I [1:0] a_rd_d_o_1 => rd_data1_o, -- O [31:0] b_wr_a_i_1 => wr_addr_i(8 downto 0), -- [8:0] b_wr_d_i_1 => post_wr_data, -- [31:0] b_wr_en_i_1 => b_wr_en_1, --{write_en & (wr_addr_i[10:9] == 2'b01)}), -- I b_rd_d_o_1 => w_pre_wr_data1(31 downto 0), -- [31:0] b_rd_en_i_1 => wr_addr_1, --{wr_addr_i[10:9] == 2'b01}), -- I a_rd_a_i_2 => rd_addr_i(8 downto 0), -- I [8:0] a_rd_en_i_2 => rd_data2_en, -- I [1:0] a_rd_d_o_2 => rd_data2_o, -- O [31:0] b_wr_a_i_2 => wr_addr_i(8 downto 0), -- I [8:0] b_wr_d_i_2 => post_wr_data, -- I [31:0] b_wr_en_i_2 => b_wr_en_2, --{write_en & (wr_addr_i[10:9] == 2'b10)}), -- I b_rd_d_o_2 => w_pre_wr_data2(31 downto 0), -- I [31:0] b_rd_en_i_2 => wr_addr_2, --{wr_addr_i[10:9] == 2'b10}), -- I a_rd_a_i_3 => rd_addr_i(8 downto 0), -- [8:0] a_rd_en_i_3 => rd_data3_en, -- [1:0] a_rd_d_o_3 => rd_data3_o, -- O [31:0] b_wr_a_i_3 => wr_addr_i(8 downto 0), -- I [8:0] b_wr_d_i_3 => post_wr_data, -- I [31:0] b_wr_en_i_3 => b_wr_en_3, --{write_en & (wr_addr_i(10 downto 9) == 2'b11)}), -- I b_rd_d_o_3 => w_pre_wr_data3(31 downto 0), -- I [31:0] b_rd_en_i_3 => wr_addr_3 --{wr_addr_i[10:9] == 2'b11} -- I ); end; -- PIO_EP_MEM_ACCESS