##// END OF EJS Templates
Fusion avec JC
Fusion avec JC

File last commit:

r129:8459a437c1f1 alexis
r203:3be1e1320f77 merge paul
Show More
ahb2mig_sp605.vhd
508 lines | 16.5 KiB | text/x-vhdl | VhdlLexer
------------------------------------------------------------------------------
-- 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;