ahb2mig_sp605.vhd
508 lines
| 16.5 KiB
| text/x-vhdl
|
VhdlLexer
r129 | ------------------------------------------------------------------------------ | |||
-- This file is a part of the GRLIB VHDL IP LIBRARY | ||||
-- Copyright (C) 2003 - 2008, Gaisler Research | ||||
-- Copyright (C) 2008 - 2012, Aeroflex Gaisler | ||||
-- | ||||
-- This program is free software; you can redistribute it and/or modify | ||||
-- it under the terms of the GNU General Public License as published by | ||||
-- the Free Software Foundation; either version 2 of the License, or | ||||
-- (at your option) any later version. | ||||
-- | ||||
-- This program is distributed in the hope that it will be useful, | ||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
-- GNU General Public License for more details. | ||||
-- | ||||
-- You should have received a copy of the GNU General Public License | ||||
-- along with this program; if not, write to the Free Software | ||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
------------------------------------------------------------------------------- | ||||
-- Entity: ahb2mig_sp605 | ||||
-- File: ahb2mig_sp605.vhd | ||||
-- Author: Jiri Gaisler - Aeroflex Gaisler AB | ||||
-- | ||||
-- This is a AHB-2.0 interface for the Xilinx Spartan-6 MIG. | ||||
-- One bidir 32-bit port is used for the main AHB bus, while | ||||
-- a second read-only port can be enabled for a VGA frame buffer. | ||||
------------------------------------------------------------------------------- | ||||
library ieee; | ||||
use ieee.std_logic_1164.all; | ||||
library grlib; | ||||
use grlib.amba.all; | ||||
use grlib.stdlib.all; | ||||
use grlib.devices.all; | ||||
entity ahb2mig_sp605 is | ||||
generic( | ||||
hindex : integer := 0; | ||||
haddr : integer := 0; | ||||
hmask : integer := 16#f00#; | ||||
pindex : integer := 0; | ||||
paddr : integer := 0; | ||||
pmask : integer := 16#fff#; | ||||
vgamst : integer := 0; | ||||
vgaburst : integer := 0 | ||||
); | ||||
port( | ||||
mcb3_dram_dq : inout std_logic_vector(15 downto 0); | ||||
mcb3_dram_a : out std_logic_vector(12 downto 0); | ||||
mcb3_dram_ba : out std_logic_vector(2 downto 0); | ||||
mcb3_dram_ras_n : out std_logic; | ||||
mcb3_dram_cas_n : out std_logic; | ||||
mcb3_dram_we_n : out std_logic; | ||||
mcb3_dram_odt : out std_logic; | ||||
mcb3_dram_reset_n : out std_logic; | ||||
mcb3_dram_cke : out std_logic; | ||||
mcb3_dram_dm : out std_logic; | ||||
mcb3_dram_udqs : inout std_logic; | ||||
mcb3_dram_udqs_n : inout std_logic; | ||||
mcb3_rzq : inout std_logic; | ||||
mcb3_zio : inout std_logic; | ||||
mcb3_dram_udm : out std_logic; | ||||
mcb3_dram_dqs : inout std_logic; | ||||
mcb3_dram_dqs_n : inout std_logic; | ||||
mcb3_dram_ck : out std_logic; | ||||
mcb3_dram_ck_n : out std_logic; | ||||
ahbso : out ahb_slv_out_type; | ||||
ahbsi : in ahb_slv_in_type; | ||||
ahbmi : out ahb_mst_in_type; | ||||
ahbmo : in ahb_mst_out_type; | ||||
apbi : in apb_slv_in_type; | ||||
apbo : out apb_slv_out_type; | ||||
calib_done : out std_logic; | ||||
rst_n_syn : in std_logic; | ||||
rst_n_async : in std_logic; | ||||
clk_amba : in std_logic; | ||||
clk_mem_p : in std_logic; | ||||
clk_mem_n : in std_logic; | ||||
clk_125 : out std_logic; | ||||
clk_50 : out std_logic | ||||
); | ||||
end ; | ||||
architecture rtl of ahb2mig_sp605 is | ||||
type bstate_type is (idle, start, read1); | ||||
constant hconfig : ahb_config_type := ( | ||||
0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_MIGDDR2, 0, 0, 0), | ||||
4 => ahb_membar(haddr, '1', '1', hmask), | ||||
-- 5 => ahb_iobar(ioaddr, iomask), | ||||
others => zero32); | ||||
constant pconfig : apb_config_type := ( | ||||
0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_MIGDDR2, 0, 0, 0), | ||||
1 => apb_iobar(paddr, pmask)); | ||||
type reg_type is record | ||||
bstate : bstate_type; | ||||
cmd_bl : std_logic_vector(5 downto 0); | ||||
wr_count : std_logic_vector(6 downto 0); | ||||
rd_cnt : std_logic_vector(5 downto 0); | ||||
hready : std_logic; | ||||
hsel : std_logic; | ||||
hwrite : std_logic; | ||||
htrans : std_logic_vector(1 downto 0); | ||||
hburst : std_logic_vector(2 downto 0); | ||||
hsize : std_logic_vector(2 downto 0); | ||||
hrdata : std_logic_vector(31 downto 0); | ||||
haddr : std_logic_vector(31 downto 0); | ||||
hmaster : std_logic_vector(3 downto 0); | ||||
end record; | ||||
type mcb_type is record | ||||
cmd_en : std_logic; | ||||
cmd_instr : std_logic_vector(2 downto 0); | ||||
cmd_empty : std_logic; | ||||
cmd_full : std_logic; | ||||
cmd_bl : std_logic_vector(5 downto 0); | ||||
cmd_byte_addr : std_logic_vector(29 downto 0); | ||||
wr_full : std_logic; | ||||
wr_empty : std_logic; | ||||
wr_underrun : std_logic; | ||||
wr_error : std_logic; | ||||
wr_mask : std_logic_vector(3 downto 0); | ||||
wr_en : std_logic; | ||||
wr_data : std_logic_vector(31 downto 0); | ||||
wr_count : std_logic_vector(6 downto 0); | ||||
rd_data : std_logic_vector(31 downto 0); | ||||
rd_full : std_logic; | ||||
rd_empty : std_logic; | ||||
rd_count : std_logic_vector(6 downto 0); | ||||
rd_overflow : std_logic; | ||||
rd_error : std_logic; | ||||
rd_en : std_logic; | ||||
end record; | ||||
type reg2_type is record | ||||
bstate : bstate_type; | ||||
cmd_bl : std_logic_vector(5 downto 0); | ||||
rd_cnt : std_logic_vector(5 downto 0); | ||||
hready : std_logic; | ||||
hsel : std_logic; | ||||
hrdata : std_logic_vector(31 downto 0); | ||||
haddr : std_logic_vector(31 downto 0); | ||||
end record; | ||||
type p2_if_type is record | ||||
cmd_en : std_logic; | ||||
cmd_instr : std_logic_vector(2 downto 0); | ||||
cmd_bl : std_logic_vector(5 downto 0); | ||||
cmd_empty : std_logic; | ||||
cmd_full : std_logic; | ||||
rd_en : std_logic; | ||||
rd_data : std_logic_vector(31 downto 0); | ||||
rd_full : std_logic; | ||||
rd_empty : std_logic; | ||||
rd_count : std_logic_vector(6 downto 0); | ||||
rd_overflow : std_logic; | ||||
rd_error : std_logic; | ||||
end record; | ||||
signal r, rin : reg_type; | ||||
signal r2, r2in : reg2_type; | ||||
signal i : mcb_type; | ||||
signal p2 : p2_if_type; | ||||
begin | ||||
comb: process( rst_n_syn, r, ahbsi, i ) | ||||
variable v : reg_type; | ||||
variable wmask : std_logic_vector(3 downto 0); | ||||
variable wr_en : std_logic; | ||||
variable cmd_en : std_logic; | ||||
variable cmd_instr : std_logic_vector(2 downto 0); | ||||
variable rd_en : std_logic; | ||||
variable cmd_bl : std_logic_vector(5 downto 0); | ||||
variable hwdata : std_logic_vector(31 downto 0); | ||||
variable readdata : std_logic_vector(31 downto 0); | ||||
begin | ||||
v := r; wr_en := '0'; cmd_en := '0'; cmd_instr := "000"; | ||||
rd_en := '0'; | ||||
if (ahbsi.hready = '1') then | ||||
if (ahbsi.hsel(hindex) and ahbsi.htrans(1)) = '1' then | ||||
v.hsel := '1'; v.hburst := ahbsi.hburst; | ||||
v.hwrite := ahbsi.hwrite; v.hsize := ahbsi.hsize; | ||||
v.hmaster := ahbsi.hmaster; | ||||
v.hready := '0'; | ||||
if ahbsi.htrans(0) = '0' then v.haddr := ahbsi.haddr; end if; | ||||
else | ||||
v.hsel := '0'; v.hready := '1'; | ||||
end if; | ||||
v.htrans := ahbsi.htrans; | ||||
end if; | ||||
hwdata := ahbsi.hwdata(15 downto 0) & ahbsi.hwdata(31 downto 16); | ||||
case r.hsize(1 downto 0) is | ||||
when "00" => wmask := not decode(r.haddr(1 downto 0)); | ||||
case r.haddr(1 downto 0) is | ||||
when "00" => wmask := "1101"; | ||||
when "01" => wmask := "1110"; | ||||
when "10" => wmask := "0111"; | ||||
when others => wmask := "1011"; | ||||
end case; | ||||
when "01" => wmask := not decode(r.haddr(1 downto 0)); | ||||
wmask(3) := wmask(2); wmask(1) := wmask(0); | ||||
when others => wmask := "0000"; | ||||
end case; | ||||
i.wr_mask <= wmask; | ||||
cmd_bl := r.cmd_bl; | ||||
case r.bstate is | ||||
when idle => | ||||
if v.hsel = '1' then | ||||
v.bstate := start; | ||||
v.hready := ahbsi.hwrite and not i.cmd_full and not i.wr_full; | ||||
v.haddr := ahbsi.haddr; | ||||
end if; | ||||
v.cmd_bl := (others => '0'); | ||||
when start => | ||||
if r.hwrite = '1' then | ||||
v.haddr := r.haddr; | ||||
if r.hready = '1' then | ||||
v.cmd_bl := r.cmd_bl + 1; v.hready := '1'; wr_en := '1'; | ||||
if (ahbsi.htrans /= "11") then | ||||
if v.hsel = '1' then | ||||
if (ahbsi.hwrite = '0') or (i.wr_count >= "0000100") then | ||||
v.hready := '0'; | ||||
else v.hready := '1'; end if; | ||||
else v.bstate := idle; end if; | ||||
v.cmd_bl := (others => '0'); v.haddr := ahbsi.haddr; | ||||
cmd_en := '1'; | ||||
elsif (i.cmd_full = '1') then | ||||
v.hready := '0'; | ||||
elsif (i.wr_count >= "0101111") then | ||||
v.hready := '0'; cmd_en := '1'; | ||||
v.cmd_bl := (others => '0'); v.haddr := ahbsi.haddr; | ||||
end if; | ||||
else | ||||
if (i.cmd_full = '0') and (i.wr_count <= "0001111") then | ||||
v.hready := '1'; | ||||
end if; | ||||
end if; | ||||
else | ||||
if i.cmd_full = '0' then | ||||
cmd_en := '1'; cmd_instr(0) := '1'; | ||||
v.cmd_bl := "000" & not r.haddr(4 downto 2); | ||||
cmd_bl := v.cmd_bl; | ||||
v.bstate := read1; | ||||
end if; | ||||
end if; | ||||
when read1 => | ||||
v.hready := '0'; | ||||
if (r.rd_cnt = "000000") then -- flush data from previous line | ||||
if (i.rd_empty = '0') or ((r.hready = '1') and (ahbsi.htrans /= "11")) then | ||||
v.hrdata(31 downto 0) := i.rd_data(15 downto 0) & i.rd_data(31 downto 16); | ||||
v.hready := '1'; | ||||
if (i.rd_empty = '0') then v.cmd_bl := r.cmd_bl - 1; rd_en := '1'; end if; | ||||
if (r.cmd_bl = "000000") or (ahbsi.htrans /= "11") then | ||||
if (ahbsi.hsel(hindex) = '1') and (ahbsi.htrans = "10") and (r.hready = '1') then | ||||
v.bstate := start; v.hready := ahbsi.hwrite and not i.cmd_full and not i.wr_full; | ||||
v.cmd_bl := (others => '0'); | ||||
else | ||||
v.bstate := idle; | ||||
end if; | ||||
if (i.rd_empty = '1') then v.rd_cnt := r.cmd_bl + 1; | ||||
else v.rd_cnt := r.cmd_bl; end if; | ||||
end if; | ||||
end if; | ||||
end if; | ||||
when others => | ||||
end case; | ||||
readdata := (others => '0'); | ||||
-- case apbi.paddr(5 downto 2) is | ||||
-- when "0000" => readdata(nbits-1 downto 0) := r.din2; | ||||
-- when "0001" => readdata(nbits-1 downto 0) := r.dout; | ||||
-- when others => | ||||
-- end case; | ||||
readdata(20 downto 0) := | ||||
i.rd_error & i.rd_overflow & i.wr_error & i.wr_underrun & | ||||
i.cmd_full & i.rd_full & i.rd_empty & i.wr_full & i.wr_empty & | ||||
r.rd_cnt & r.cmd_bl; | ||||
if (r.rd_cnt /= "000000") and (i.rd_empty = '0') then | ||||
rd_en := '1'; v.rd_cnt := r.rd_cnt - 1; | ||||
end if; | ||||
if rst_n_syn = '0' then | ||||
v.rd_cnt := "000000"; v.bstate := idle; v.hready := '1'; | ||||
end if; | ||||
rin <= v; | ||||
apbo.prdata <= readdata; | ||||
i.rd_en <= rd_en; | ||||
i.wr_en <= wr_en; | ||||
i.cmd_bl <= cmd_bl; | ||||
i.cmd_en <= cmd_en; | ||||
i.cmd_instr <= cmd_instr; | ||||
i.wr_data <= hwdata; | ||||
end process; | ||||
i.cmd_byte_addr <= r.haddr(29 downto 2) & "00"; | ||||
ahbso.hready <= r.hready; | ||||
ahbso.hresp <= "00"; --r.hresp; | ||||
ahbso.hrdata <= r.hrdata; | ||||
ahbso.hconfig <= hconfig; | ||||
ahbso.hirq <= (others => '0'); | ||||
ahbso.hindex <= hindex; | ||||
ahbso.hsplit <= (others => '0'); | ||||
ahbso.hcache <= '1'; | ||||
apbo.pindex <= pindex; | ||||
apbo.pconfig <= pconfig; | ||||
apbo.pirq <= (others => '0'); | ||||
regs : process(clk_amba) | ||||
begin | ||||
if rising_edge(clk_amba) then | ||||
r <= rin; | ||||
end if; | ||||
end process; | ||||
port2 : if vgamst /= 0 generate | ||||
comb2: process( rst_n_syn, r2, ahbmo, p2 ) | ||||
variable v2 : reg2_type; | ||||
variable cmd_en : std_logic; | ||||
variable rd_en : std_logic; | ||||
begin | ||||
v2 := r2; cmd_en := '0'; rd_en := '0'; | ||||
case r2.bstate is | ||||
when idle => | ||||
if ahbmo.htrans(1) = '1' then | ||||
v2.bstate := start; | ||||
v2.hready := '0'; | ||||
v2.haddr := ahbmo.haddr; | ||||
else v2.hready := '1'; end if; | ||||
v2.cmd_bl := (others => '0'); | ||||
when start => | ||||
if p2.cmd_full = '0' then | ||||
cmd_en := '1'; | ||||
v2.cmd_bl := conv_std_logic_vector(vgaburst-1, 6); | ||||
v2.bstate := read1; | ||||
end if; | ||||
when read1 => | ||||
v2.hready := '0'; | ||||
if (r2.rd_cnt = "000000") then -- flush data from previous line | ||||
if (p2.rd_empty = '0') or ((r2.hready = '1') and (ahbmo.htrans /= "11")) then | ||||
v2.hrdata(31 downto 0) := p2.rd_data(15 downto 0) & p2.rd_data(31 downto 16); | ||||
v2.hready := '1'; | ||||
if (p2.rd_empty = '0') then v2.cmd_bl := r2.cmd_bl - 1; rd_en := '1'; end if; | ||||
if (r2.cmd_bl = "000000") or (ahbmo.htrans /= "11") then | ||||
if (ahbmo.htrans = "10") and (r2.hready = '1') then | ||||
v2.bstate := start; v2.hready := '0'; | ||||
v2.cmd_bl := (others => '0'); | ||||
else | ||||
v2.bstate := idle; | ||||
end if; | ||||
if (p2.rd_empty = '1') then v2.rd_cnt := r2.cmd_bl + 1; | ||||
else v2.rd_cnt := r2.cmd_bl; end if; | ||||
end if; | ||||
end if; | ||||
end if; | ||||
when others => | ||||
end case; | ||||
if (r2.rd_cnt /= "000000") and (p2.rd_empty = '0') then | ||||
rd_en := '1'; v2.rd_cnt := r2.rd_cnt - 1; | ||||
end if; | ||||
v2.haddr(1 downto 0) := "00"; | ||||
if rst_n_syn = '0' then | ||||
v2.rd_cnt := "000000"; v2.bstate := idle; v2.hready := '1'; | ||||
end if; | ||||
r2in <= v2; | ||||
p2.rd_en <= rd_en; | ||||
p2.cmd_bl <= v2.cmd_bl; | ||||
p2.cmd_en <= cmd_en; | ||||
p2.cmd_instr <= "001"; | ||||
end process; | ||||
ahbmi.hrdata <= r2.hrdata; | ||||
ahbmi.hresp <= "00"; | ||||
ahbmi.hgrant <= (others => '1'); | ||||
ahbmi.hready <= r2.hready; | ||||
ahbmi.hcache <= '0'; | ||||
ahbmi.hirq <= (others => '0'); | ||||
ahbmi.testen <= '0'; | ||||
ahbmi.testrst <= '0'; | ||||
ahbmi.scanen <= '0'; | ||||
ahbmi.testoen <= '0'; | ||||
regs : process(clk_amba) | ||||
begin | ||||
if rising_edge(clk_amba) then | ||||
r2 <= r2in; | ||||
end if; | ||||
end process; | ||||
end generate; | ||||
noport2 : if vgamst = 0 generate | ||||
p2.cmd_en <= '0'; | ||||
p2.rd_en <= '0'; | ||||
end generate; | ||||
MCB_inst : entity work.mig_38 generic map( | ||||
C3_P0_MASK_SIZE => 4, | ||||
C3_P0_DATA_PORT_SIZE => 32, | ||||
C3_P1_MASK_SIZE => 4, | ||||
C3_P1_DATA_PORT_SIZE => 32, | ||||
-- C3_MEMCLK_PERIOD => 5000, | ||||
C3_RST_ACT_LOW => 1, | ||||
C3_INPUT_CLK_TYPE => "DIFFERENTIAL", | ||||
C3_CALIB_SOFT_IP => "TRUE", | ||||
-- pragma translate_off | ||||
C3_SIMULATION => "TRUE", | ||||
-- pragma translate_on | ||||
C3_MEM_ADDR_ORDER => "BANK_ROW_COLUMN", | ||||
C3_NUM_DQ_PINS => 16, | ||||
C3_MEM_ADDR_WIDTH => 13, | ||||
C3_MEM_BANKADDR_WIDTH => 3 | ||||
) | ||||
port map ( | ||||
mcb3_dram_dq => mcb3_dram_dq, | ||||
mcb3_dram_a => mcb3_dram_a, | ||||
mcb3_dram_ba => mcb3_dram_ba, | ||||
mcb3_dram_ras_n => mcb3_dram_ras_n, | ||||
mcb3_dram_cas_n => mcb3_dram_cas_n, | ||||
mcb3_dram_we_n => mcb3_dram_we_n, | ||||
mcb3_dram_odt => mcb3_dram_odt, | ||||
mcb3_dram_reset_n => mcb3_dram_reset_n, | ||||
mcb3_dram_cke => mcb3_dram_cke, | ||||
mcb3_dram_dm => mcb3_dram_dm, | ||||
mcb3_dram_udqs => mcb3_dram_udqs, | ||||
mcb3_dram_udqs_n => mcb3_dram_udqs_n, | ||||
mcb3_rzq => mcb3_rzq, | ||||
mcb3_zio => mcb3_zio, | ||||
mcb3_dram_udm => mcb3_dram_udm, | ||||
c3_sys_clk_p => clk_mem_p, | ||||
c3_sys_clk_n => clk_mem_n, | ||||
c3_sys_rst_i => rst_n_async, | ||||
c3_calib_done => calib_done, | ||||
c3_clk0 => open, | ||||
c3_rst0 => open, | ||||
mcb3_dram_dqs => mcb3_dram_dqs, | ||||
mcb3_dram_dqs_n => mcb3_dram_dqs_n, | ||||
mcb3_dram_ck => mcb3_dram_ck, | ||||
mcb3_dram_ck_n => mcb3_dram_ck_n, | ||||
c3_p0_cmd_clk => clk_amba, | ||||
c3_p0_cmd_en => i.cmd_en, | ||||
c3_p0_cmd_instr => i.cmd_instr, | ||||
c3_p0_cmd_bl => i.cmd_bl, | ||||
c3_p0_cmd_byte_addr => i.cmd_byte_addr, | ||||
c3_p0_cmd_empty => i.cmd_empty, | ||||
c3_p0_cmd_full => i.cmd_full, | ||||
c3_p0_wr_clk => clk_amba, | ||||
c3_p0_wr_en => i.wr_en, | ||||
c3_p0_wr_mask => i.wr_mask, | ||||
c3_p0_wr_data => i.wr_data, | ||||
c3_p0_wr_full => i.wr_full, | ||||
c3_p0_wr_empty => i.wr_empty, | ||||
c3_p0_wr_count => i.wr_count, | ||||
c3_p0_wr_underrun => i.wr_underrun, | ||||
c3_p0_wr_error => i.wr_error, | ||||
c3_p0_rd_clk => clk_amba, | ||||
c3_p0_rd_en => i.rd_en, | ||||
c3_p0_rd_data => i.rd_data, | ||||
c3_p0_rd_full => i.rd_full, | ||||
c3_p0_rd_empty => i.rd_empty, | ||||
c3_p0_rd_count => i.rd_count, | ||||
c3_p0_rd_overflow => i.rd_overflow, | ||||
c3_p0_rd_error => i.rd_error, | ||||
c3_p2_cmd_clk => clk_amba, | ||||
c3_p2_cmd_en => p2.cmd_en, | ||||
c3_p2_cmd_instr => p2.cmd_instr, | ||||
c3_p2_cmd_bl => p2.cmd_bl, | ||||
c3_p2_cmd_byte_addr => r2.haddr(29 downto 0), | ||||
c3_p2_cmd_empty => p2.cmd_empty, | ||||
c3_p2_cmd_full => p2.cmd_full, | ||||
c3_p2_rd_clk => clk_amba, | ||||
c3_p2_rd_en => p2.rd_en, | ||||
c3_p2_rd_data => p2.rd_data, | ||||
c3_p2_rd_full => p2.rd_full, | ||||
c3_p2_rd_empty => p2.rd_empty, | ||||
c3_p2_rd_count => p2.rd_count, | ||||
c3_p2_rd_overflow => p2.rd_overflow, | ||||
c3_p2_rd_error => p2.rd_error, | ||||
clk_125 => clk_125, | ||||
clk_50 => clk_50 | ||||
); | ||||
end; | ||||