diff --git a/lib/SDRAM/ddr_sdr_v1_5/ise9/sdram_ctrl_top.prj b/lib/SDRAM/ddr_sdr_v1_5/ise9/sdram_ctrl_top.prj
new file mode 100644
index 0000000..334db73
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/ise9/sdram_ctrl_top.prj
@@ -0,0 +1,13 @@
+vhdl work "../../../misc/utils_pkg.vhd"
+vhdl work "../src/sdram_config.vhd"
+vhdl work "../../../FIFO/src/fifo_ctrl_pkg.vhd"
+vhdl work "../src/sdram_types.vhd"
+vhdl work "../../../FIFO/src/sync_fifo_ctrl.vhd"
+vhdl work "../../../FIFO/src/dpram.vhd"
+vhdl work "../src/sdram_ctrl.vhd"
+vhdl work "../src/sdram_cmd.vhd"
+vhdl work "../src/reset_virtex4.vhd"
+vhdl work "../src/fifo_sync.vhd"
+vhdl work "../src/ddr_phy_virtex4.vhd"
+vhdl work "../src/clockgen_virtex4.vhd"
+vhdl work "../src/sdram_ctrl_top.vhd"
diff --git a/lib/SDRAM/ddr_sdr_v1_5/sim/ModelSim SE .lnk b/lib/SDRAM/ddr_sdr_v1_5/sim/ModelSim SE .lnk
new file mode 100644
index 0000000..e0d2d27
Binary files /dev/null and b/lib/SDRAM/ddr_sdr_v1_5/sim/ModelSim SE .lnk differ
diff --git a/lib/SDRAM/ddr_sdr_v1_5/sim/compile_simprim.do b/lib/SDRAM/ddr_sdr_v1_5/sim/compile_simprim.do
new file mode 100644
index 0000000..16b23bb
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/sim/compile_simprim.do
@@ -0,0 +1,6 @@
+vlib simprim
+
+vcom -93 -work simprim F:/Xilinx9/vhdl/src/simprims/simprim_Vcomponents_mti.vhd
+vcom -93 -work simprim F:/Xilinx9/vhdl/src/simprims/simprim_Vpackage_mti.vhd
+vcom -93 -work simprim F:/Xilinx9/vhdl/src/simprims/simprim_SMODEL_mti.vhd
+vcom -93 -work simprim F:/Xilinx9/vhdl/src/simprims/simprim_VITAL_mti.vhd
diff --git a/lib/SDRAM/ddr_sdr_v1_5/sim/compile_unisim.do b/lib/SDRAM/ddr_sdr_v1_5/sim/compile_unisim.do
new file mode 100644
index 0000000..d35d8c9
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/sim/compile_unisim.do
@@ -0,0 +1,6 @@
+vlib unisim
+
+vcom -93 -work unisim F:/Xilinx9/vhdl/src/unisims/unisim_vpkg.vhd
+vcom -93 -work unisim F:/Xilinx9/vhdl/src/unisims/unisim_vcomp.vhd
+vcom -93 -work unisim F:/Xilinx9/vhdl/src/unisims/unisim_smodel.vhd
+vcom -93 -work unisim F:/Xilinx9/vhdl/src/unisims/unisim_vital.vhd
diff --git a/lib/SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo b/lib/SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo
new file mode 100644
index 0000000..c7f5f7f
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo
@@ -0,0 +1,28 @@
+## NOTE: Do not edit this file.
+##
+
+vlib work
+vcom -explicit -93 "../../../FIFO/src/fifo_ctrl_pkg.vhd"
+vcom -explicit -93 "../../../misc/dpram_1w1r_dist.vhd"
+vcom -explicit -93 "../../../FIFO/src/sync_fifo_ctrl.vhd"
+vcom -explicit -93 "../../../misc/utils_pkg.vhd"
+vcom -explicit -93 "../../../misc/clockgen_virtex4.vhd"
+vcom -explicit -93 "../src/fifo_sync.vhd"
+vcom -explicit -93 "../src/sdram_config.vhd"
+vcom -explicit -93 "../src/sdram_types.vhd"
+vcom -explicit -93 "../src/reset_virtex4.vhd"
+vcom -explicit -93 "../src/sdram_cmd.vhd"
+vcom -explicit -93 "../src/sdram_ctrl.vhd"
+vcom -explicit -93 "../src/ddr_phy_virtex4.vhd"
+vcom -explicit -93 "../src/sdram_ctrl_top.vhd"
+vcom -explicit -93 "../src/sdram_ctrl_frontend_wb.vhd"
+vcom -explicit -93 "../src/mt46v16m16.vhd"
+vcom -explicit -93 "../src/tb_sdram_ctrl_frontend_wb.vhd"
+
+#restart -force
+vsim -t 1ps -lib work tb_sdram_ctrl_frontend_wb
+do {tb_sdram_ctrl_frontend_wb.wdo}
+view wave
+view structure
+view signals
+run 40us
diff --git a/lib/SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.wdo b/lib/SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.wdo
new file mode 100644
index 0000000..f2b1282
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.wdo
@@ -0,0 +1,31 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/clk_o
+add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/rst_o
+add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/cyc_o
+add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/stb_o
+add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/we_o
+add wave -noupdate -format Literal /tb_sdram_ctrl_frontend_wb/sel_o
+add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/ack_i
+add wave -noupdate -format Logic /tb_sdram_ctrl_frontend_wb/rdy_i
+add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/addr_o
+add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/dat_i
+add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/dat_o
+add wave -noupdate -format Literal -radix hexadecimal /tb_sdram_ctrl_frontend_wb/dout_reg
+add wave -noupdate -format Literal /tb_sdram_ctrl_frontend_wb/dout_cnt
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {7168067 ps} 0}
+configure wave -namecolwidth 150
+configure wave -valuecolwidth 100
+configure wave -justifyvalue left
+configure wave -signalnamewidth 1
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+update
+WaveRestoreZoom {7132020 ps} {7288781 ps}
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/ddr_phy_virtex4.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/ddr_phy_virtex4.vhd
new file mode 100644
index 0000000..f5ab332
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/ddr_phy_virtex4.vhd
@@ -0,0 +1,389 @@
+-------------------------------------------------------------------------
+-- Project: SDRAM controller
+-- This file: DDR physical layer (Virtex-4 specific)
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+use work.sdram_config.all;
+use work.sdram_types.all;
+
+Library UNISIM;
+use UNISIM.vcomponents.all;
+
+entity ddr_phy is
+ Port (
+ sys_rst : in STD_LOGIC;
+ sys_clk0 : in STD_LOGIC;
+ sys_clk270 : in STD_LOGIC;
+ u_tag_in : in user_tag_t;
+ u_tag_rd : out user_tag_t;
+ u_tag_wr : out user_tag_t;
+ read_clk : in STD_LOGIC;
+ phy_ctrl : in phy_ctrl_t;
+ part_ctrl : in part_ctrl_t;
+ sdr_data_w : in unsigned(SDR_DATA_WIDTH-1 downto 0);
+ sdr_dm_wr_in : in unsigned(SDR_DM_WIDTH-1 downto 0);
+ sdr_dm_rd_in : in unsigned(SDR_DM_WIDTH-1 downto 0);
+ sdr_dm_rd_out : out unsigned(SDR_DM_WIDTH-1 downto 0);
+ sdr_data_r : out unsigned(SDR_DATA_WIDTH-1 downto 0);
+ sdr_data_vld : out STD_LOGIC;
+ sdr_data_req_w : out STD_LOGIC;
+ sdr_data_req_r : out STD_LOGIC;
+ part_clk_p : out STD_LOGIC;
+ part_clk_n : out STD_LOGIC;
+ part_dm : out unsigned(DDR_DM_WIDTH-1 downto 0);
+ part_dqs : inout unsigned(DDR_DQS_WIDTH-1 downto 0);
+ part_data : inout unsigned(DDR_DATA_WIDTH-1 downto 0);
+ part_ba : out unsigned(DDR_BANK_WIDTH-1 downto 0);
+ part_addr : out unsigned(DDR_ADDR_WIDTH-1 downto 0);
+ part_cs_n : out STD_LOGIC;
+ part_we_n : out STD_LOGIC;
+ part_cas_n : out STD_LOGIC;
+ part_ras_n : out STD_LOGIC;
+ part_cke : out STD_LOGIC
+ );
+end ddr_phy;
+
+architecture tech of ddr_phy is
+
+ signal dqs_drive : std_logic;
+ signal drive : std_logic;
+ signal dqs : unsigned(DDR_DQS_WIDTH-1 downto 0);
+ signal dqs_zen : unsigned(DDR_DQS_WIDTH-1 downto 0);
+ signal dqs_rst : std_logic;
+ signal ddr_data_w : unsigned(DDR_DATA_WIDTH-1 downto 0);
+ signal data_r : unsigned(SDR_DATA_WIDTH-1 downto 0);
+ signal data_reg_r : unsigned(SDR_DATA_WIDTH-1 downto 0);
+ signal drive270 : unsigned(DDR_DATA_WIDTH-1 downto 0);
+ signal part_ctrl_reg : part_ctrl_t;
+ signal we_reg : std_logic;
+ signal read_en : std_logic;
+
+ type u_tag_array_t is array (natural range 0 to 4) of user_tag_t;
+ signal u_tag_pipe : u_tag_array_t;
+
+ type dm_out_array_t is array (natural range 0 to 4) of unsigned(SDR_DM_WIDTH-1 downto 0);
+ signal dm_out_pipe : dm_out_array_t;
+
+begin
+
+------------------------------------------------------------------------------------------------------------------------------------------------
+utag_pipe:
+ process(sys_rst, sys_clk0)
+ begin
+ if rising_edge(sys_clk0) then
+ for i in u_tag_pipe'length-1 downto 1 loop
+ u_tag_pipe(i) <= u_tag_pipe(i-1);
+ end loop;
+ if phy_ctrl.utag_we = '1' then
+ u_tag_pipe(0) <= u_tag_in;
+ end if;
+ end if;
+ end process;
+
+dmout_pipe:
+ process(sys_rst, sys_clk0)
+ begin
+ if rising_edge(sys_clk0) then
+ for i in dm_out_pipe'length-1 downto 1 loop
+ dm_out_pipe(i) <= dm_out_pipe(i-1);
+ end loop;
+ if phy_ctrl.utag_we = '1' then
+ dm_out_pipe(0) <= sdr_dm_rd_in;
+ end if;
+ end if;
+ end process;
+
+WE_REGISTER:
+ process(sys_rst, sys_clk0)
+ begin
+ if sys_rst = '1' then
+ we_reg <= '0';
+ elsif rising_edge(sys_clk0) then
+ we_reg <= phy_ctrl.we;
+ end if;
+ end process;
+
+DATA_DRIVE_GEN:
+ process(sys_clk0)
+ begin
+ if falling_edge(sys_clk0) then
+ dqs_rst <= not we_reg;
+ drive <= we_reg;
+ end if;
+ end process;
+
+DQS_DRIVE_GEN:
+ process(sys_clk0)
+ variable p : unsigned(1 downto 0);
+ begin
+ if rising_edge(sys_clk0) then
+ if phy_ctrl.drive_en = '1' then
+ p := (others => '1');
+ else
+ p := p(p'left-1 downto 0) & '0';
+ end if;
+ end if;
+ dqs_drive <= p(p'left);
+ end process;
+
+------------------------------------------------------------------------------------------------------------------------------------------------
+-- SDRAM Clock
+ODDR_clk_p : ODDR
+ generic map
+ (
+ DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
+ INIT => '0', -- Initial value for Q port ('1' or '0')
+ SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
+ )
+ port map (
+ Q => part_clk_p, -- 1-bit DDR output
+ C => sys_clk0, -- 1-bit clock input
+ CE => '1', -- 1-bit clock enable input
+ D1 => '1', -- 1-bit data input (positive edge)
+ D2 => '0', -- 1-bit data input (negative edge)
+ R => '0', -- 1-bit reset input
+ S => '0' -- 1-bit set input
+ );
+
+ODDR_clk_n : ODDR
+ generic map
+ (
+ DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
+ INIT => '0', -- Initial value for Q port ('1' or '0')
+ SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
+ )
+ port map (
+ Q => part_clk_n, -- 1-bit DDR output
+ C => sys_clk0, -- 1-bit clock input
+ CE => '1', -- 1-bit clock enable input
+ D1 => '0', -- 1-bit data input (positive edge)
+ D2 => '1', -- 1-bit data input (negative edge)
+ R => '0', -- 1-bit reset input
+ S => '0' -- 1-bit set input
+ );
+
+------------------------------------------------------------------------------------------------------------------------------------------------
+-- Data OUT DDR-FFs
+gen_ddr_data_out:
+ for n in 0 to DDR_DATA_WIDTH-1 generate
+ begin
+ ODDR_data : ODDR
+ generic map
+ (
+ DDR_CLK_EDGE => "SAME_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
+ INIT => '0', -- Initial value for Q port ('1' or '0')
+ SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
+ )
+ port map (
+ Q => ddr_data_w(n), -- 1-bit DDR output
+ C => sys_clk270, -- 1-bit clock input
+ CE => '1', -- 1-bit clock enable input
+ D1 => sdr_data_w(n + DDR_DATA_WIDTH), -- 1-bit data input (positive edge)
+ D2 => sdr_data_w(n), -- 1-bit data input (negative edge)
+ R => '0', -- 1-bit reset input
+ S => '0' -- 1-bit set input
+ );
+ end generate gen_ddr_data_out;
+
+-- Sample tristate on clock90
+ process (sys_clk270)
+ begin
+ if rising_edge(sys_clk270) then
+ for n in 0 to DDR_DATA_WIDTH-1 loop
+ drive270(n) <= drive;
+ end loop;
+ end if;
+ end process;
+
+-- Output mux
+out_mux_data:
+ for n in 0 to DDR_DATA_WIDTH-1 generate
+ part_data(n) <= ddr_data_w(n) when drive270(n) = '1' else 'Z';
+ end generate;
+
+------------------------------------------------------------------------------------------------------------------------------------------------
+-- Data-mask OUT DDR-FFs
+gen_ddr_dm_out:
+ for n in 0 to DDR_DM_WIDTH-1 generate
+ begin
+ ODDR_dm : ODDR
+ generic map
+ (
+ DDR_CLK_EDGE => "SAME_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
+ INIT => '0', -- Initial value for Q port ('1' or '0')
+ SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
+ )
+ port map (
+ Q => part_dm(n), -- 1-bit DDR output
+ C => sys_clk270, -- 1-bit clock input
+ CE => '1', -- 1-bit clock enable input
+ D1 => sdr_dm_wr_in(n + DDR_DM_WIDTH), -- 1-bit data input (positive edge)
+ D2 => sdr_dm_wr_in(n), -- 1-bit data input (negative edge)
+ R => '0', -- 1-bit reset input
+ S => '0' -- 1-bit set input
+ );
+ end generate gen_ddr_dm_out;
+
+------------------------------------------------------------------------------------------------------------------------------------------------
+-- DQS OUT DDR-FFs
+gen_dqs_out:
+ for n in 0 to DDR_DQS_WIDTH-1 generate
+ begin
+ ODDR_dqs : ODDR
+ generic map
+ (
+ DDR_CLK_EDGE => "OPPOSITE_EDGE", -- "OPPOSITE_EDGE" or "SAME_EDGE"
+ INIT => '0', -- Initial value for Q port ('1' or '0')
+ SRTYPE => "SYNC" -- Reset Type ("ASYNC" or "SYNC")
+ )
+ port map (
+ Q => dqs(n), -- 1-bit DDR output
+ C => sys_clk0, -- 1-bit clock input
+ CE => '1', -- 1-bit clock enable input
+ D2 => '0', -- 1-bit data input (positive edge)
+ D1 => '1', -- 1-bit data input (negative edge)
+ R => dqs_rst, -- 1-bit reset input
+ S => '0' -- 1-bit set input
+ );
+ end generate gen_dqs_out;
+
+-- Tristate-Control fuer dqs
+ process (sys_clk0) is
+ variable zctrl : boolean;
+ begin
+ if rising_edge(sys_clk0) then
+ if dqs_drive = '1' then
+ zctrl := false;
+ else
+ zctrl := true;
+ end if;
+ if zctrl then
+ dqs_zen <= (others => '1');
+ else
+ dqs_zen <= (others => '0');
+ end if;
+ end if;
+ end process;
+
+-- Tristate-Buffer fuer dqs
+gen_out_mux_dqs:
+ for n in 0 to DDR_DQS_WIDTH-1 generate
+ part_dqs(n) <= 'Z' when dqs_zen(n)='1' else dqs(n);
+ end generate gen_out_mux_dqs;
+
+------------------------------------------------------------------------------------------------------------------------------------------------
+ process (sys_rst, sys_clk0) is
+ begin
+ if sys_rst = '1' then
+ part_ctrl_reg.cmd <= COMMAND(SD_DESELECT);
+ part_ctrl_reg.ba <= (others=>'0');
+ part_ctrl_reg.addr <= (others=>'0');
+ part_ctrl_reg.cke <= '0';
+ elsif rising_edge(sys_clk0) then
+ part_ctrl_reg <= part_ctrl;
+ end if;
+ end process;
+
+ process (sys_clk0) is
+ begin
+ if falling_edge(sys_clk0) then
+ part_ras_n <= part_ctrl_reg.cmd.ras_n;
+ part_cas_n <= part_ctrl_reg.cmd.cas_n;
+ part_we_n <= part_ctrl_reg.cmd.we_n;
+ part_cs_n <= part_ctrl_reg.cmd.cs_n;
+ part_ba <= part_ctrl_reg.ba;
+ part_addr <= part_ctrl_reg.addr;
+ part_cke <= part_ctrl_reg.cke;
+ end if;
+ end process;
+
+-----------------------------------------------------------------
+-- READ DATA Processing
+-----------------------------------------------------------------
+gen_ddr_data_in:
+ for n in 0 to DDR_DATA_WIDTH-1 generate
+ begin
+ IDDR_data : IDDR
+ generic map
+ (
+ DDR_CLK_EDGE => "SAME_EDGE", -- "OPPOSITE_EDGE", "SAME_EDGE" or "SAME_EDGE_PIPELINED"
+ INIT_Q1 => '0', -- Initial value of Q1: '0' or '1'
+ INIT_Q2 => '0', -- Initial value of Q2: '0' or '1'
+ SRTYPE => "SYNC" -- Set/Reset type: "SYNC" or "ASYNC"
+ )
+ port map
+ (
+ Q1 => data_r(n), -- 1-bit output for positive edge of clock
+ Q2 => data_r(n + DDR_DATA_WIDTH), -- 1-bit output for negative edge of clock
+ C => read_clk, -- 1-bit clock input
+ CE => read_en, -- 1-bit clock enable input
+ D => part_data(n), -- 1-bit DDR data input
+ R => '0', -- 1-bit reset
+ S => '0' -- 1-bit set
+ );
+ end generate;
+
+
+data_sample_stage:
+ process (sys_clk0)
+ begin
+ if falling_edge(sys_clk0) then
+ data_reg_r <= data_r;
+ end if;
+ end process;
+
+misc_flags_and_data_out:
+ process (sys_rst, sys_clk0)
+ variable p : unsigned(3 downto 0);
+ begin
+ if sys_rst = '1' then
+ p := (others => '0');
+ read_en <= '0';
+ sdr_data_vld <= '0';
+ sdr_data_req_w <= '0';
+ sdr_data_req_r <= '0';
+ elsif rising_edge(sys_clk0) then
+ sdr_data_r <= data_reg_r;
+ if p(3) = '1' then
+ u_tag_rd <= u_tag_pipe(4);
+ sdr_dm_rd_out <= dm_out_pipe(4);
+ end if;
+ if phy_ctrl.we = '1' then
+ u_tag_wr <= u_tag_pipe(0);
+ end if;
+ sdr_data_req_w <= phy_ctrl.we;
+ sdr_data_req_r <= phy_ctrl.re;
+ sdr_data_vld <= p(3);
+ read_en <= p(1);
+ if phy_ctrl.re = '1' then
+ p := p(p'left-1 downto 0) & '1';
+ else
+ p := p(p'left-1 downto 0) & '0';
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+end tech;
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/fifo_sync.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/fifo_sync.vhd
new file mode 100644
index 0000000..79ce51f
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/fifo_sync.vhd
@@ -0,0 +1,111 @@
+-------------------------------------------------------------------------
+-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
+-- This file: Dual-ported register file with asynchrous read
+
+-- Copyright (C) 2007 J. Ahrensfeld
+
+-- This library is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU Lesser General Public
+-- License as published by the Free Software Foundation; either
+-- version 2.1 of the License, or (at your option) any later version.
+
+-- This library 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
+-- Lesser General Public License for more details.
+
+-- You should have received a copy of the GNU Lesser General Public
+-- License along with this library; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+-- For questions and ideas, please contact the author at jens@jayfield.org
+
+-----------------------------------------------------------------------
+
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+
+use work.fifo_ctrl_pkg.all;
+
+entity fifo_sync is
+ Generic (
+ addr_width : natural := 4;
+ data_width : natural := 8;
+ almost_full_thresh : integer := 12;
+ almost_empty_thresh : integer := 4
+ );
+ Port
+ (
+ rst : in STD_LOGIC;
+ clk : in STD_LOGIC;
+ we : in STD_LOGIC;
+ re : in STD_LOGIC;
+ fifo_full : out STD_LOGIC;
+ fifo_empty : out STD_LOGIC;
+ fifo_afull : out STD_LOGIC;
+ fifo_aempty : out STD_LOGIC;
+ data_w : in unsigned (data_width-1 downto 0);
+ data_r : out unsigned (data_width-1 downto 0)
+ );
+end fifo_sync;
+
+architecture Behavioral of fifo_sync is
+
+ signal mem_we : STD_LOGIC;
+ signal ptr_w : unsigned (addr_width-1 downto 0);
+ signal ptr_r : unsigned (addr_width-1 downto 0);
+ signal full : STD_LOGIC;
+ signal empty : STD_LOGIC;
+ signal almost_full : STD_LOGIC;
+ signal almost_empty : STD_LOGIC;
+
+begin
+
+ mem_we <= we;
+ fifo_full <= full;
+ fifo_empty <= empty;
+ fifo_afull <= almost_full;
+ fifo_aempty <= almost_empty;
+
+ inst_sync_fifo_ctrl: entity work.sync_fifo_ctrl
+ GENERIC MAP
+ (
+ addr_width => addr_width,
+ almost_full_thresh => almost_full_thresh,
+ almost_empty_thresh => almost_empty_thresh
+ )
+ PORT MAP
+ (
+ rst => rst,
+ clk => clk,
+ we => we,
+ re => re,
+ ptr_w => ptr_w,
+ ptr_r => ptr_r,
+ fifo_full => full,
+ fifo_empty => empty,
+ fifo_afull => almost_full,
+ fifo_aempty => almost_empty
+
+ );
+
+ inst_dpram_1w1r: entity work.dpram_1w1r_dist
+ GENERIC MAP (
+ addr_width => addr_width,
+ data_width => data_width
+ )
+ PORT MAP(
+ clka => clk,
+ clkb => clk,
+ en_a => '1',
+ en_b => '1',
+ we_a => mem_we,
+ addr_a => ptr_w,
+ addr_b => ptr_r,
+ din_a => data_w,
+ dout_b => data_r
+ );
+
+end Behavioral;
+
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/mt46v16m16.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/mt46v16m16.vhd
new file mode 100644
index 0000000..356bb28
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/mt46v16m16.vhd
@@ -0,0 +1,1320 @@
+-----------------------------------------------------------------------------------------
+--
+-- File Name: MT46V16M16.VHD
+-- Version: 2.1
+-- Date: January 14th, 2002
+-- Model: Behavioral
+-- Simulator: NCDesktop - http://www.cadence.com
+-- ModelSim PE - http://www.model.com
+--
+-- Dependencies: None
+--
+-- Author: Son P. Huynh
+-- Email: sphuynh@micron.com
+-- Phone: (208) 368-3825
+-- Company: Micron Technology, Inc.
+-- Part Number: MT46V16M16 (4 Mb x 16 x 4 Banks)
+--
+-- Description: Micron 256 Mb SDRAM DDR (Double Data Rate)
+--
+-- Limitation: Doesn't model internal refresh counter
+--
+-- Note:
+--
+-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
+-- WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
+-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
+-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
+--
+-- Copyright (c) 1998 Micron Semiconductor Products, Inc.
+-- All rights researved
+--
+-- Rev Author Date Changes
+-- --- ---------------------------- ---------- -------------------------------------
+-- 2.1 Son P. Huynh 01/14/2002 - Fix Burst_counter
+-- Micron Technology, Inc.
+--
+-- 2.0 Son P. Huynh 11/08/2001 - Second release
+-- Micron Technology, Inc. - Rewrote and remove SHARED VARIABLE
+--
+-----------------------------------------------------------------------------------------
+
+LIBRARY IEEE;
+ USE IEEE.STD_LOGIC_1164.ALL;
+ USE IEEE.STD_LOGIC_UNSIGNED.ALL;
+ USE IEEE.STD_LOGIC_ARITH.ALL;
+
+ENTITY MT46V16M16 IS
+ GENERIC ( -- Timing for -75Z CL2
+ tCK : TIME := 7.500 ns;
+ tCH : TIME := 3.375 ns; -- 0.45*tCK
+ tCL : TIME := 3.375 ns; -- 0.45*tCK
+ tDH : TIME := 0.500 ns;
+ tDS : TIME := 0.500 ns;
+ tIH : TIME := 0.900 ns;
+ tIS : TIME := 0.900 ns;
+ tMRD : TIME := 15.000 ns;
+ tRAS : TIME := 40.000 ns;
+ tRAP : TIME := 20.000 ns;
+ tRC : TIME := 65.000 ns;
+ tRFC : TIME := 75.000 ns;
+ tRCD : TIME := 20.000 ns;
+ tRP : TIME := 20.000 ns;
+ tRRD : TIME := 15.000 ns;
+ tWR : TIME := 15.000 ns;
+ addr_bits : INTEGER := 13;
+ data_bits : INTEGER := 16;
+ cols_bits : INTEGER := 9
+ );
+ PORT (
+ Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
+ Dqs : INOUT STD_LOGIC_VECTOR (1 DOWNTO 0) := "ZZ";
+ Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ Ba : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
+ Clk : IN STD_LOGIC;
+ Clk_n : IN STD_LOGIC;
+ Cke : IN STD_LOGIC;
+ Cs_n : IN STD_LOGIC;
+ Ras_n : IN STD_LOGIC;
+ Cas_n : IN STD_LOGIC;
+ We_n : IN STD_LOGIC;
+ Dm : IN STD_LOGIC_VECTOR (1 DOWNTO 0)
+ );
+END MT46V16M16;
+
+ARCHITECTURE behave OF MT46V16M16 IS
+ -- Array for Read pipeline
+ TYPE Array_Read_cmnd IS ARRAY (8 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Read_bank IS ARRAY (8 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0);
+ TYPE Array_Read_cols IS ARRAY (8 DOWNTO 0) OF STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0);
+
+ -- Array for Write pipeline
+ TYPE Array_Write_cmnd IS ARRAY (2 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Write_bank IS ARRAY (2 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0);
+ TYPE Array_Write_cols IS ARRAY (2 DOWNTO 0) OF STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0);
+
+ -- Array for Auto Precharge
+ TYPE Array_Read_precharge IS ARRAY (3 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Write_precharge IS ARRAY (3 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Count_precharge IS ARRAY (3 DOWNTO 0) OF INTEGER;
+
+ -- Array for Manual Precharge
+ TYPE Array_A10_precharge IS ARRAY (8 DOWNTO 0) OF STD_LOGIC;
+ TYPE Array_Bank_precharge IS ARRAY (8 DOWNTO 0) OF STD_LOGIC_VECTOR (1 DOWNTO 0);
+ TYPE Array_Cmnd_precharge IS ARRAY (8 DOWNTO 0) OF STD_LOGIC;
+
+ -- Array for Burst Terminate
+ TYPE Array_Cmnd_bst IS ARRAY (8 DOWNTO 0) OF STD_LOGIC;
+
+ -- Array for Memory Access
+ TYPE Array_ram_type IS ARRAY (2**cols_bits - 1 DOWNTO 0) OF STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0);
+ TYPE Array_ram_pntr IS ACCESS Array_ram_type;
+ TYPE Array_ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF Array_ram_pntr;
+
+ -- Data pair
+ SIGNAL Dq_pair : STD_LOGIC_VECTOR (2 * data_bits - 1 DOWNTO 0);
+ SIGNAL Dm_pair : STD_LOGIC_VECTOR (3 DOWNTO 0);
+
+ -- Mode Register
+ SIGNAL Mode_reg : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
+
+ -- Command Decode Variables
+ SIGNAL Active_enable, Aref_enable, Burst_term, Ext_mode_enable : STD_LOGIC := '0';
+ SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : STD_LOGIC := '0';
+
+ -- Burst Length Decode Variables
+ SIGNAL Burst_length_2, Burst_length_4, Burst_length_8, Burst_length_f : STD_LOGIC := '0';
+
+ -- Cas Latency Decode Variables
+ SIGNAL Cas_latency_15, Cas_latency_2, Cas_latency_25, Cas_latency_3, Cas_latency_4 : STD_LOGIC := '0';
+
+ -- Internal Control Signals
+ SIGNAL Cs_in, Ras_in, Cas_in, We_in : STD_LOGIC := '0';
+
+ -- System Clock
+ SIGNAL Sys_clk : STD_LOGIC := '0';
+
+ -- Dqs buffer
+ SIGNAL Dqs_out : STD_LOGIC_VECTOR (1 DOWNTO 0) := "ZZ";
+
+BEGIN
+ -- Strip the strength
+ Cs_in <= To_X01 (Cs_n);
+ Ras_in <= To_X01 (Ras_n);
+ Cas_in <= To_X01 (Cas_n);
+ We_in <= To_X01 (We_n);
+
+ -- Commands Decode
+ Active_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND We_in;
+ Aref_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND We_in;
+ Burst_term <= NOT(Cs_in) AND Ras_in AND Cas_in AND NOT(We_in);
+ Ext_mode_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in) AND Ba(0) AND NOT(Ba(1));
+ Mode_reg_enable <= NOT(Cs_in) AND NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in) AND NOT(Ba(0)) AND NOT(Ba(1));
+ Prech_enable <= NOT(Cs_in) AND NOT(Ras_in) AND Cas_in AND NOT(We_in);
+ Read_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND We_in;
+ Write_enable <= NOT(Cs_in) AND Ras_in AND NOT(Cas_in) AND NOT(We_in);
+
+ -- Burst Length Decode
+ Burst_length_2 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND Mode_reg(0);
+ Burst_length_4 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND NOT(Mode_reg(0));
+ Burst_length_8 <= NOT(Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0);
+ Burst_length_f <= (Mode_reg(2)) AND Mode_reg(1) AND Mode_reg(0);
+
+ -- CAS Latency Decode
+ Cas_latency_15 <= Mode_reg(6) AND NOT(Mode_reg(5)) AND (Mode_reg(4));
+ Cas_latency_2 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND NOT(Mode_reg(4));
+ Cas_latency_25 <= Mode_reg(6) AND Mode_reg(5) AND NOT(Mode_reg(4));
+ Cas_latency_3 <= NOT(Mode_reg(6)) AND Mode_reg(5) AND Mode_reg(4);
+ Cas_latency_4 <= (Mode_reg(6)) AND NOT(Mode_reg(5)) AND NOT(Mode_reg(4));
+
+ -- Dqs buffer
+ Dqs <= Dqs_out;
+
+ --
+ -- System Clock
+ --
+ int_clk : PROCESS (Clk, Clk_n)
+ VARIABLE ClkZ, CkeZ : STD_LOGIC := '0';
+ begin
+ IF Clk = '1' AND Clk_n = '0' THEN
+ ClkZ := '1';
+ CkeZ := Cke;
+ ELSIF Clk = '0' AND Clk_n = '1' THEN
+ ClkZ := '0';
+ END IF;
+ Sys_clk <= CkeZ AND ClkZ;
+ END PROCESS;
+
+ --
+ -- Main Process
+ --
+ state_register : PROCESS
+ -- Precharge Variables
+ VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : STD_LOGIC := '0';
+
+ -- Activate Variables
+ VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : STD_LOGIC := '1';
+
+ -- Data IO variables
+ VARIABLE Data_in_enable, Data_out_enable : STD_LOGIC := '0';
+
+ -- Internal address mux variables
+ VARIABLE Cols_brst : STD_LOGIC_VECTOR (2 DOWNTO 0);
+ VARIABLE Prev_bank : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00";
+ VARIABLE Bank_addr : STD_LOGIC_VECTOR (1 DOWNTO 0) := "00";
+ VARIABLE Cols_addr : STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0);
+ VARIABLE Rows_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ VARIABLE B0_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ VARIABLE B1_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ VARIABLE B2_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+ VARIABLE B3_row_addr : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
+
+ -- DLL Reset variables
+ VARIABLE DLL_enable : STD_LOGIC := '0';
+ VARIABLE DLL_reset : STD_LOGIC := '0';
+ VARIABLE DLL_done : STD_LOGIC := '0';
+ VARIABLE DLL_count : INTEGER := 0;
+
+ -- Timing Check
+ VARIABLE MRD_chk : TIME := 0 ns;
+ VARIABLE RFC_chk : TIME := 0 ns;
+ VARIABLE RRD_chk : TIME := 0 ns;
+ VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 : TIME := 0 ns;
+ VARIABLE RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3 : TIME := 0 ns;
+ VARIABLE RC_chk0, RC_chk1, RC_chk2, RC_chk3 : TIME := 0 ns;
+ VARIABLE RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 : TIME := 0 ns;
+ VARIABLE RP_chk0, RP_chk1, RP_chk2, RP_chk3 : TIME := 0 ns;
+ VARIABLE WR_chk0, WR_chk1, WR_chk2, WR_chk3 : TIME := 0 ns;
+
+ -- Read pipeline variables
+ VARIABLE Read_cmnd : Array_Read_cmnd;
+ VARIABLE Read_bank : Array_Read_bank;
+ VARIABLE Read_cols : Array_Read_cols;
+
+ -- Write pipeline variables
+ VARIABLE Write_cmnd : Array_Write_cmnd;
+ VARIABLE Write_bank : Array_Write_bank;
+ VARIABLE Write_cols : Array_Write_cols;
+
+ -- Auto Precharge variables
+ VARIABLE Read_precharge : Array_Read_precharge := ('0' & '0' & '0' & '0');
+ VARIABLE Write_precharge : Array_Write_precharge := ('0' & '0' & '0' & '0');
+ VARIABLE Count_precharge : Array_Count_precharge := ( 0 & 0 & 0 & 0 );
+
+ -- Manual Precharge variables
+ VARIABLE A10_precharge : Array_A10_precharge;
+ VARIABLE Bank_precharge : Array_Bank_precharge;
+ VARIABLE Cmnd_precharge : Array_Cmnd_precharge;
+
+ -- Burst Terminate variable
+ VARIABLE Cmnd_bst : Array_Cmnd_bst;
+
+ -- Memory Banks
+ VARIABLE Bank0 : Array_ram_stor;
+ VARIABLE Bank1 : Array_ram_stor;
+ VARIABLE Bank2 : Array_ram_stor;
+ VARIABLE Bank3 : Array_ram_stor;
+
+ -- Burst Counter
+ VARIABLE Burst_counter : STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0);
+
+ -- Internal Dqs initialize
+ VARIABLE Dqs_int : STD_LOGIC := '0';
+
+ -- Data buffer for DM Mask
+ VARIABLE Data_buf : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
+
+ --
+ -- Initialize empty rows
+ --
+ PROCEDURE Init_mem (Bank : STD_LOGIC_VECTOR; Row_index : INTEGER) IS
+ VARIABLE i, j : INTEGER := 0;
+ BEGIN
+ IF Bank = "00" THEN
+ IF Bank0 (Row_index) = NULL THEN -- Check to see if row empty
+ Bank0 (Row_index) := NEW Array_ram_type; -- Open new row for access
+ FOR i IN (2**cols_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros
+ FOR j IN (data_bits - 1) DOWNTO 0 LOOP
+ Bank0 (Row_index) (i) (j) := '0';
+ END LOOP;
+ END LOOP;
+ END IF;
+ ELSIF Bank = "01" THEN
+ IF Bank1 (Row_index) = NULL THEN
+ Bank1 (Row_index) := NEW Array_ram_type;
+ FOR i IN (2**cols_bits - 1) DOWNTO 0 LOOP
+ FOR j IN (data_bits - 1) DOWNTO 0 LOOP
+ Bank1 (Row_index) (i) (j) := '0';
+ END LOOP;
+ END LOOP;
+ END IF;
+ ELSIF Bank = "10" THEN
+ IF Bank2 (Row_index) = NULL THEN
+ Bank2 (Row_index) := NEW Array_ram_type;
+ FOR i IN (2**cols_bits - 1) DOWNTO 0 LOOP
+ FOR j IN (data_bits - 1) DOWNTO 0 LOOP
+ Bank2 (Row_index) (i) (j) := '0';
+ END LOOP;
+ END LOOP;
+ END IF;
+ ELSIF Bank = "11" THEN
+ IF Bank3 (Row_index) = NULL THEN
+ Bank3 (Row_index) := NEW Array_ram_type;
+ FOR i IN (2**cols_bits - 1) DOWNTO 0 LOOP
+ FOR j IN (data_bits - 1) DOWNTO 0 LOOP
+ Bank3 (Row_index) (i) (j) := '0';
+ END LOOP;
+ END LOOP;
+ END IF;
+ END IF;
+ END;
+
+ --
+ -- Burst Counter
+ --
+ PROCEDURE Burst_decode IS
+ VARIABLE Cols_temp : STD_LOGIC_VECTOR (cols_bits - 1 DOWNTO 0) := (OTHERS => '0');
+ BEGIN
+ -- Advance burst counter
+ Burst_counter := Burst_counter + 1;
+
+ -- Burst Type
+ IF Mode_reg (3) = '0' THEN
+ Cols_temp := Cols_addr + 1;
+ ELSIF Mode_reg (3) = '1' THEN
+ Cols_temp (2) := Burst_counter (2) XOR Cols_brst (2);
+ Cols_temp (1) := Burst_counter (1) XOR Cols_brst (1);
+ Cols_temp (0) := Burst_counter (0) XOR Cols_brst (0);
+ END IF;
+
+ -- Burst Length
+ IF Burst_length_2 = '1' THEN
+ Cols_addr (0) := Cols_temp (0);
+ ELSIF Burst_length_4 = '1' THEN
+ Cols_addr (1 DOWNTO 0) := Cols_temp (1 DOWNTO 0);
+ ELSIF Burst_length_8 = '1' THEN
+ Cols_addr (2 DOWNTO 0) := Cols_temp (2 DOWNTO 0);
+ ELSE
+ Cols_addr := Cols_temp;
+ END IF;
+
+ -- Data counter
+ IF Burst_length_2 = '1' THEN
+ IF Burst_counter >= 2 THEN
+ IF Data_in_enable = '1' THEN
+ Data_in_enable := '0';
+ ELSIF Data_out_enable = '1' THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+ ELSIF Burst_length_4 = '1' THEN
+ IF Burst_counter >= 4 THEN
+ IF Data_in_enable = '1' THEN
+ Data_in_enable := '0';
+ ELSIF Data_out_enable = '1' THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+ ELSIF Burst_length_8 = '1' THEN
+ IF Burst_counter >= 8 THEN
+ IF Data_in_enable = '1' THEN
+ Data_in_enable := '0';
+ ELSIF Data_out_enable = '1' THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+ END IF;
+ END;
+
+ BEGIN
+ WAIT ON Sys_clk;
+
+ --
+ -- Manual Precharge Pipeline
+ --
+ IF ((Sys_clk'EVENT AND Sys_clk = '0') OR (Sys_clk'EVENT AND Sys_clk = '1')) THEN
+ -- A10 Precharge Pipeline
+ A10_precharge(0) := A10_precharge(1);
+ A10_precharge(1) := A10_precharge(2);
+ A10_precharge(2) := A10_precharge(3);
+ A10_precharge(3) := A10_precharge(4);
+ A10_precharge(4) := A10_precharge(5);
+ A10_precharge(5) := A10_precharge(6);
+ A10_precharge(6) := A10_precharge(7);
+ A10_precharge(7) := A10_precharge(8);
+ A10_precharge(8) := '0';
+
+ -- Bank Precharge Pipeline
+ Bank_precharge(0) := Bank_precharge(1);
+ Bank_precharge(1) := Bank_precharge(2);
+ Bank_precharge(2) := Bank_precharge(3);
+ Bank_precharge(3) := Bank_precharge(4);
+ Bank_precharge(4) := Bank_precharge(5);
+ Bank_precharge(5) := Bank_precharge(6);
+ Bank_precharge(6) := Bank_precharge(7);
+ Bank_precharge(7) := Bank_precharge(8);
+ Bank_precharge(8) := "00";
+
+ -- Command Precharge Pipeline
+ Cmnd_precharge(0) := Cmnd_precharge(1);
+ Cmnd_precharge(1) := Cmnd_precharge(2);
+ Cmnd_precharge(2) := Cmnd_precharge(3);
+ Cmnd_precharge(3) := Cmnd_precharge(4);
+ Cmnd_precharge(4) := Cmnd_precharge(5);
+ Cmnd_precharge(5) := Cmnd_precharge(6);
+ Cmnd_precharge(6) := Cmnd_precharge(7);
+ Cmnd_precharge(7) := Cmnd_precharge(8);
+ Cmnd_precharge(8) := '0';
+
+ -- Terminate Read if same bank or all banks
+ IF ((Cmnd_precharge (0) = '1') AND
+ (Bank_precharge (0) = Bank_addr OR A10_precharge (0) = '1') AND
+ (Data_out_enable = '1')) THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+
+ --
+ -- Burst Terminate Pipeline
+ --
+ IF ((Sys_clk'EVENT AND Sys_clk = '0') OR (Sys_clk'EVENT AND Sys_clk = '1')) THEN
+ -- Burst Terminate pipeline
+ Cmnd_bst (0) := Cmnd_bst (1);
+ Cmnd_bst (1) := Cmnd_bst (2);
+ Cmnd_bst (2) := Cmnd_bst (3);
+ Cmnd_bst (3) := Cmnd_bst (4);
+ Cmnd_bst (4) := Cmnd_bst (5);
+ Cmnd_bst (5) := Cmnd_bst (6);
+ Cmnd_bst (6) := Cmnd_bst (7);
+ Cmnd_bst (7) := Cmnd_bst (8);
+ Cmnd_bst (8) := '0';
+
+ -- Terminate current Read
+ IF ((Cmnd_bst (0) = '1') AND (Data_out_enable = '1')) THEN
+ Data_out_enable := '0';
+ END IF;
+ END IF;
+
+ --
+ -- Dq and Dqs Drivers
+ --
+ IF ((Sys_clk'EVENT AND Sys_clk = '0') OR (Sys_clk'EVENT AND Sys_clk = '1')) THEN
+ -- Read Command Pipeline
+ Read_cmnd (0) := Read_cmnd (1);
+ Read_cmnd (1) := Read_cmnd (2);
+ Read_cmnd (2) := Read_cmnd (3);
+ Read_cmnd (3) := Read_cmnd (4);
+ Read_cmnd (4) := Read_cmnd (5);
+ Read_cmnd (5) := Read_cmnd (6);
+ Read_cmnd (6) := Read_cmnd (7);
+ Read_cmnd (7) := Read_cmnd (8);
+ Read_cmnd (8) := '0';
+
+ -- Read Bank Pipeline
+ Read_bank (0) := Read_bank (1);
+ Read_bank (1) := Read_bank (2);
+ Read_bank (2) := Read_bank (3);
+ Read_bank (3) := Read_bank (4);
+ Read_bank (4) := Read_bank (5);
+ Read_bank (5) := Read_bank (6);
+ Read_bank (6) := Read_bank (7);
+ Read_bank (7) := Read_bank (8);
+ Read_bank (8) := "00";
+
+ -- Read Column Pipeline
+ Read_cols (0) := Read_cols (1);
+ Read_cols (1) := Read_cols (2);
+ Read_cols (2) := Read_cols (3);
+ Read_cols (3) := Read_cols (4);
+ Read_cols (4) := Read_cols (5);
+ Read_cols (5) := Read_cols (6);
+ Read_cols (6) := Read_cols (7);
+ Read_cols (7) := Read_cols (8);
+ Read_cols (8) := (OTHERS => '0');
+
+ -- Initialize Read command
+ IF Read_cmnd (0) = '1' THEN
+ Data_out_enable := '1';
+ Bank_addr := Read_bank (0);
+ Cols_addr := Read_cols (0);
+ Cols_brst := Cols_addr (2 DOWNTO 0);
+ Burst_counter := (OTHERS => '0');
+
+ -- Row address mux
+ CASE Bank_addr IS
+ WHEN "00" => Rows_addr := B0_row_addr;
+ WHEN "01" => Rows_addr := B1_row_addr;
+ WHEN "10" => Rows_addr := B2_row_addr;
+ WHEN OTHERS => Rows_addr := B3_row_addr;
+ END CASE;
+ END IF;
+
+ -- Toggle Dqs during Read command
+ IF Data_out_enable = '1' THEN
+ Dqs_int := '0';
+ IF Dqs_out = "00" THEN
+ Dqs_out <= "11";
+ ELSIF Dqs_out = "11" THEN
+ Dqs_out <= "00";
+ ELSE
+ Dqs_out <= "00";
+ END IF;
+ ELSIF Data_out_enable = '0' AND Dqs_int = '0' THEN
+ Dqs_out <= "ZZ";
+ END IF;
+
+ -- Initialize Dqs for Read command
+ IF Read_cmnd (2) = '1' THEN
+ IF Data_out_enable = '0' THEN
+ Dqs_int := '1';
+ Dqs_out <= "00";
+ END IF;
+ END IF;
+
+ -- Read Latch
+ IF Data_out_enable = '1' THEN
+ -- Initialize Memory
+ Init_mem (Bank_addr, CONV_INTEGER(Rows_addr));
+
+ -- Output Data
+ CASE Bank_addr IS
+ WHEN "00" => Dq <= Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "01" => Dq <= Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "10" => Dq <= Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN OTHERS => Dq <= Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ END CASE;
+
+ -- Increase Burst Counter
+ Burst_decode;
+ ELSE
+ Dq <= (OTHERS => 'Z');
+ END IF;
+ END IF;
+
+ --
+ -- Write FIFO and DM Mask Logic
+ --
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ -- Write command pipeline
+ Write_cmnd (0) := Write_cmnd (1);
+ Write_cmnd (1) := Write_cmnd (2);
+ Write_cmnd (2) := '0';
+
+ -- Write command pipeline
+ Write_bank (0) := Write_bank (1);
+ Write_bank (1) := Write_bank (2);
+ Write_bank (2) := "00";
+
+ -- Write column pipeline
+ Write_cols (0) := Write_cols (1);
+ Write_cols (1) := Write_cols (2);
+ Write_cols (2) := (OTHERS => '0');
+
+ -- Initialize Write command
+ IF Write_cmnd (0) = '1' THEN
+ Data_in_enable := '1';
+ Bank_addr := Write_bank (0);
+ Cols_addr := Write_cols (0);
+ Cols_brst := Cols_addr (2 DOWNTO 0);
+ Burst_counter := (OTHERS => '0');
+
+ -- Row address mux
+ CASE Bank_addr IS
+ WHEN "00" => Rows_addr := B0_row_addr;
+ WHEN "01" => Rows_addr := B1_row_addr;
+ WHEN "10" => Rows_addr := B2_row_addr;
+ WHEN OTHERS => Rows_addr := B3_row_addr;
+ END CASE;
+ END IF;
+
+ -- Write data
+ IF Data_in_enable = '1' THEN
+ -- Initialize memory
+ Init_mem (Bank_addr, CONV_INTEGER(Rows_addr));
+
+ -- Write first data
+ IF Dm_pair (1) = '0' OR Dm_pair (0) = '0' THEN
+ -- Data Buffer
+ CASE Bank_addr IS
+ WHEN "00" => Data_buf := Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "01" => Data_buf := Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "10" => Data_buf := Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN OTHERS => Data_buf := Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ END CASE;
+
+ -- Perform DM Mask
+ IF Dm_pair (0) = '0' THEN
+ Data_buf ( 7 DOWNTO 0) := Dq_pair ( 7 DOWNTO 0);
+ END IF;
+ IF Dm_pair (1) = '0' THEN
+ Data_buf (15 DOWNTO 8) := Dq_pair (15 DOWNTO 8);
+ END IF;
+
+ -- Write Data
+ CASE Bank_addr IS
+ WHEN "00" => Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN "01" => Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN "10" => Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN OTHERS => Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ END CASE;
+ END IF;
+
+ -- Increase Burst Counter
+ Burst_decode;
+
+ -- Write second data
+ IF Dm_pair (3) = '0' OR Dm_pair (2) = '0' THEN
+ -- Data Buffer
+ CASE Bank_addr IS
+ WHEN "00" => Data_buf := Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "01" => Data_buf := Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN "10" => Data_buf := Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ WHEN OTHERS => Data_buf := Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr));
+ END CASE;
+
+ -- Perform DM Mask
+ IF Dm_pair (2) = '0' THEN
+ Data_buf ( 7 DOWNTO 0) := Dq_pair (23 DOWNTO 16);
+ END IF;
+ IF Dm_pair (3) = '0' THEN
+ Data_buf (15 DOWNTO 8) := Dq_pair (31 DOWNTO 24);
+ END IF;
+
+ -- Write Data
+ CASE Bank_addr IS
+ WHEN "00" => Bank0 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN "01" => Bank1 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN "10" => Bank2 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ WHEN OTHERS => Bank3 (CONV_INTEGER(Rows_addr)) (CONV_INTEGER(Cols_addr)) := Data_buf;
+ END CASE;
+ END IF;
+
+ -- Increase Burst Counter
+ Burst_decode;
+
+ -- tWR start and tWTR check
+ IF Dm_pair (3 DOWNTO 2) = "00" OR Dm_pair (1 DOWNTO 0) = "00" THEN
+ CASE Bank_addr IS
+ WHEN "00" => WR_chk0 := NOW;
+ WHEN "01" => WR_chk1 := NOW;
+ WHEN "10" => WR_chk2 := NOW;
+ WHEN OTHERS => WR_chk3 := NOW;
+ END CASE;
+
+ -- tWTR check
+ ASSERT (Read_enable = '0')
+ REPORT "tWTR violation during Read"
+ SEVERITY WARNING;
+ END IF;
+ END IF;
+ END IF;
+
+ --
+ -- Auto Precharge Calculation
+ --
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ -- Precharge counter
+ IF Read_precharge (0) = '1' OR Write_precharge (0) = '1' THEN
+ Count_precharge (0) := Count_precharge (0) + 1;
+ END IF;
+ IF Read_precharge (1) = '1' OR Write_precharge (1) = '1' THEN
+ Count_precharge (1) := Count_precharge (1) + 1;
+ END IF;
+ IF Read_precharge (2) = '1' OR Write_precharge (2) = '1' THEN
+ Count_precharge (2) := Count_precharge (2) + 1;
+ END IF;
+ IF Read_precharge (3) = '1' OR Write_precharge (3) = '1' THEN
+ Count_precharge (3) := Count_precharge (3) + 1;
+ END IF;
+
+ -- Read with AutoPrecharge Calculation
+ -- The device start internal precharge when:
+ -- 1. Meet tRAS requirement
+ -- 2. BL/2 cycles after command
+ IF ((Read_precharge(0) = '1') AND (NOW - RAS_chk0 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge(0) >= 1) OR
+ (Burst_length_4 = '1' AND Count_precharge(0) >= 2) OR
+ (Burst_length_8 = '1' AND Count_precharge(0) >= 4)) THEN
+ Pc_b0 := '1';
+ Act_b0 := '0';
+ RP_chk0 := NOW;
+ Read_precharge(0) := '0';
+ END IF;
+ END IF;
+ IF ((Read_precharge(1) = '1') AND (NOW - RAS_chk1 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge(1) >= 1) OR
+ (Burst_length_4 = '1' AND Count_precharge(1) >= 2) OR
+ (Burst_length_8 = '1' AND Count_precharge(1) >= 4)) THEN
+ Pc_b1 := '1';
+ Act_b1 := '0';
+ RP_chk1 := NOW;
+ Read_precharge(1) := '0';
+ END IF;
+ END IF;
+ IF ((Read_precharge(2) = '1') AND (NOW - RAS_chk2 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge(2) >= 1) OR
+ (Burst_length_4 = '1' AND Count_precharge(2) >= 2) OR
+ (Burst_length_8 = '1' AND Count_precharge(2) >= 4)) THEN
+ Pc_b2 := '1';
+ Act_b2 := '0';
+ RP_chk2 := NOW;
+ Read_precharge(2) := '0';
+ END IF;
+ END IF;
+ IF ((Read_precharge(3) = '1') AND (NOW - RAS_chk3 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge(3) >= 1) OR
+ (Burst_length_4 = '1' AND Count_precharge(3) >= 2) OR
+ (Burst_length_8 = '1' AND Count_precharge(3) >= 4)) THEN
+ Pc_b3 := '1';
+ Act_b3 := '0';
+ RP_chk3 := NOW;
+ Read_precharge(3) := '0';
+ END IF;
+ END IF;
+
+ -- Write with AutoPrecharge Calculation
+ -- The device start internal precharge when:
+ -- 1. Meet tRAS requirement
+ -- 2. Two clock after last burst
+ -- Since tWR is time base, the model will compensate tRP
+ IF ((Write_precharge(0) = '1') AND (NOW - RAS_chk0 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge (0) >= 4) OR
+ (Burst_length_4 = '1' AND Count_precharge (0) >= 5) OR
+ (Burst_length_8 = '1' AND Count_precharge (0) >= 7)) THEN
+ Pc_b0 := '1';
+ Act_b0 := '0';
+ RP_chk0 := NOW - ((2 * tCK) - tWR);
+ Write_precharge(0) := '0';
+ END IF;
+ END IF;
+ IF ((Write_precharge(1) = '1') AND (NOW - RAS_chk1 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge (1) >= 4) OR
+ (Burst_length_4 = '1' AND Count_precharge (1) >= 5) OR
+ (Burst_length_8 = '1' AND Count_precharge (1) >= 7)) THEN
+ Pc_b1 := '1';
+ Act_b1 := '0';
+ RP_chk1 := NOW - ((2 * tCK) - tWR);
+ Write_precharge(1) := '0';
+ END IF;
+ END IF;
+ IF ((Write_precharge(2) = '1') AND (NOW - RAS_chk2 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge (2) >= 4) OR
+ (Burst_length_4 = '1' AND Count_precharge (2) >= 5) OR
+ (Burst_length_8 = '1' AND Count_precharge (2) >= 7)) THEN
+ Pc_b2 := '1';
+ Act_b2 := '0';
+ RP_chk2 := NOW - ((2 * tCK) - tWR);
+ Write_precharge(2) := '0';
+ END IF;
+ END IF;
+ IF ((Write_precharge(3) = '1') AND (NOW - RAS_chk3 >= tRAS)) THEN
+ IF ((Burst_length_2 = '1' AND Count_precharge (3) >= 4) OR
+ (Burst_length_4 = '1' AND Count_precharge (3) >= 5) OR
+ (Burst_length_8 = '1' AND Count_precharge (3) >= 7)) THEN
+ Pc_b3 := '1';
+ Act_b3 := '0';
+ RP_chk3 := NOW - ((2 * tCK) - tWR);
+ Write_precharge(3) := '0';
+ END IF;
+ END IF;
+ END IF;
+
+ --
+ -- DLL Counter
+ --
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ IF (DLL_Reset = '1' AND DLL_done = '0') THEN
+ DLL_count := DLL_count + 1;
+ IF (DLL_count >= 200) THEN
+ DLL_done := '1';
+ END IF;
+ END IF;
+ END IF;
+
+ --
+ -- Control Logic
+ --
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ -- Auto Refresh
+ IF Aref_enable = '1' THEN
+ -- Auto Refresh to Auto Refresh
+ ASSERT (NOW - RFC_chk >= tRFC)
+ REPORT "tRFC violation during Auto Refresh"
+ SEVERITY WARNING;
+
+ -- Precharge to Auto Refresh
+ ASSERT ((NOW - RP_chk0 >= tRP) AND (NOW - RP_chk1 >= tRP) AND
+ (NOW - RP_chk2 >= tRP) AND (NOW - RP_chk3 >= tRP))
+ REPORT "tRP violation during Auto Refresh"
+ SEVERITY WARNING;
+
+ -- Precharge to Auto Refresh
+ ASSERT (Pc_b0 = '1' AND Pc_b1 = '1' AND Pc_b2 = '1' AND Pc_b3 = '1')
+ REPORT "All banks must be Precharge before Auto Refresh"
+ SEVERITY WARNING;
+
+ -- Record current tRFC time
+ RFC_chk := NOW;
+ END IF;
+
+ -- Extended Load Mode Register
+ IF Ext_mode_enable = '1' THEN
+ IF (Pc_b0 = '1' AND Pc_b1 = '1' AND Pc_b2 = '1' AND Pc_b3 = '1') THEN
+ IF (Addr (0) = '0') THEN
+ DLL_enable := '1';
+ ELSE
+ DLL_enable := '0';
+ END IF;
+ END IF;
+
+ -- Precharge to EMR
+ ASSERT (Pc_b0 = '1' AND Pc_b1 = '1' AND Pc_b2 = '1' AND Pc_b3 = '1')
+ REPORT "All bank must be Precharged before Extended Mode Register"
+ SEVERITY WARNING;
+
+ -- Precharge to EMR
+ ASSERT ((NOW - RP_chk0 >= tRP) AND (NOW - RP_chk1 >= tRP) AND
+ (NOW - RP_chk2 >= tRP) AND (NOW - RP_chk3 >= tRP))
+ REPORT "tRP violation during Extended Load Register"
+ SEVERITY WARNING;
+
+ -- LMR/EMR to EMR
+ ASSERT (NOW - MRD_chk >= tMRD)
+ REPORT "tMRD violation during Extended Mode Register"
+ SEVERITY WARNING;
+
+ -- Record current tMRD time
+ MRD_chk := NOW;
+ END IF;
+
+ -- Load Mode Register
+ IF Mode_reg_enable = '1' THEN
+ -- Register mode
+ Mode_reg <= Addr;
+
+ -- DLL Reset
+ IF (DLL_enable = '1' AND Addr (8) = '1') THEN
+ DLL_reset := '1';
+ DLL_done := '0';
+ DLL_count := 0;
+ ELSIF (DLL_enable = '1' AND DLL_reset = '0' AND Addr (8) = '0') THEN
+ ASSERT (FALSE)
+ REPORT "DLL is ENABLE: DLL RESET is require"
+ SEVERITY WARNING;
+ ELSIF (DLL_enable = '0' AND Addr (8) = '1') THEN
+ ASSERT (FALSE)
+ REPORT "DLL is DISABLE: DLL RESET will be ignored"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Precharge to LMR
+ ASSERT (Pc_b0 = '1' AND Pc_b1 = '1' AND Pc_b2 = '1' AND Pc_b3 = '1')
+ REPORT "All bank must be Precharged before Load Mode Register"
+ SEVERITY WARNING;
+
+ -- Precharge to EMR
+ ASSERT ((NOW - RP_chk0 >= tRP) AND (NOW - RP_chk1 >= tRP) AND
+ (NOW - RP_chk2 >= tRP) AND (NOW - RP_chk3 >= tRP))
+ REPORT "tRP violation during Load Mode Register"
+ SEVERITY WARNING;
+
+ -- LMR/ELMR to LMR
+ ASSERT (NOW - MRD_chk >= tMRD)
+ REPORT "tMRD violation during Load Mode Register"
+ SEVERITY WARNING;
+
+ -- Check for invalid Burst Length
+ ASSERT ((Addr (2 DOWNTO 0) = "001") OR -- BL = 2
+ (Addr (2 DOWNTO 0) = "010") OR -- BL = 4
+ (Addr (2 DOWNTO 0) = "011")) -- BL = 8
+ REPORT "Invalid Burst Length during Load Mode Register"
+ SEVERITY WARNING;
+
+ -- Check for invalid CAS Latency
+ ASSERT ((Addr (6 DOWNTO 4) = "010") OR -- CL = 2.0
+ (Addr (6 DOWNTO 4) = "110")) -- CL = 2.5
+ REPORT "Invalid CAS Latency during Load Mode Register"
+ SEVERITY WARNING;
+
+ -- Record current tMRD time
+ MRD_chk := NOW;
+ END IF;
+
+ -- Active Block (latch Bank and Row Address)
+ IF Active_enable = '1' THEN
+ -- Activate an OPEN bank can corrupt data
+ ASSERT ((Ba = "00" AND Act_b0 = '0') OR
+ (Ba = "01" AND Act_b1 = '0') OR
+ (Ba = "10" AND Act_b2 = '0') OR
+ (Ba = "11" AND Act_b3 = '0'))
+ REPORT "Bank is already activated - data can be corrupted"
+ SEVERITY WARNING;
+
+ -- Activate Bank 0
+ IF Ba = "00" AND Pc_b0 = '1' THEN
+ -- Activate to Activate (same bank)
+ ASSERT (NOW - RC_chk0 >= tRC)
+ REPORT "tRC violation during Activate Bank 0"
+ SEVERITY WARNING;
+
+ -- Precharge to Active
+ ASSERT (NOW - RP_chk0 >= tRP)
+ REPORT "tRP violation during Activate Bank 0"
+ SEVERITY WARNING;
+
+ -- Record Variables for checking violation
+ Act_b0 := '1';
+ Pc_b0 := '0';
+ B0_row_addr := Addr;
+ RC_chk0 := NOW;
+ RCD_chk0 := NOW;
+ RAS_chk0 := NOW;
+ RAP_chk0 := NOW;
+ END IF;
+
+ -- Activate Bank 1
+ IF Ba = "01" AND Pc_b1 = '1' THEN
+ -- Activate to Activate (same bank)
+ ASSERT (NOW - RC_chk1 >= tRC)
+ REPORT "tRC violation during Activate Bank 1"
+ SEVERITY WARNING;
+
+ -- Precharge to Active
+ ASSERT (NOW - RP_chk1 >= tRP)
+ REPORT "tRP violation during Activate Bank 1"
+ SEVERITY WARNING;
+
+ -- Record Variables for checking violation
+ Act_b1 := '1';
+ Pc_b1 := '0';
+ B1_row_addr := Addr;
+ RC_chk1 := NOW;
+ RCD_chk1 := NOW;
+ RAS_chk1 := NOW;
+ RAP_chk1 := NOW;
+ END IF;
+
+ -- Activate Bank 2
+ IF Ba = "10" AND Pc_b2 = '1' THEN
+ -- Activate to Activate (same bank)
+ ASSERT (NOW - RC_chk2 >= tRC)
+ REPORT "tRC violation during Activate Bank 2"
+ SEVERITY WARNING;
+
+ -- Precharge to Active
+ ASSERT (NOW - RP_chk2 >= tRP)
+ REPORT "tRP violation during Activate Bank 2"
+ SEVERITY WARNING;
+
+ -- Record Variables for checking violation
+ Act_b2 := '1';
+ Pc_b2 := '0';
+ B2_row_addr := Addr;
+ RC_chk2 := NOW;
+ RCD_chk2 := NOW;
+ RAS_chk2 := NOW;
+ RAP_chk2 := NOW;
+ END IF;
+
+ -- Activate Bank 3
+ IF Ba = "11" AND Pc_b3 = '1' THEN
+ -- Activate to Activate (same bank)
+ ASSERT (NOW - RC_chk3 >= tRC)
+ REPORT "tRC violation during Activate Bank 3"
+ SEVERITY WARNING;
+
+ -- Precharge to Active
+ ASSERT (NOW - RP_chk3 >= tRP)
+ REPORT "tRP violation during Activate Bank 3"
+ SEVERITY WARNING;
+
+ -- Record Variables for checking violation
+ Act_b3 := '1';
+ Pc_b3 := '0';
+ B3_row_addr := Addr;
+ RC_chk3 := NOW;
+ RCD_chk3 := NOW;
+ RAS_chk3 := NOW;
+ RAP_chk3 := NOW;
+ END IF;
+
+ -- Activate Bank A to Activate Bank B
+ IF (Prev_bank /= Ba) THEN
+ ASSERT (NOW - RRD_chk >= tRRD)
+ REPORT "tRRD violation during Activate"
+ SEVERITY WARNING;
+ END IF;
+
+ -- AutoRefresh to Activate
+ ASSERT (NOW - RFC_chk >= tRFC)
+ REPORT "tRFC violation during Activate"
+ SEVERITY WARNING;
+
+ -- Record Variables for Checking Violation
+ RRD_chk := NOW;
+ Prev_bank := Ba;
+ END IF;
+
+ -- Precharge Block - Consider NOP if bank already precharged or in process of precharging
+ IF Prech_enable = '1' THEN
+ -- EMR or LMR to Precharge
+ ASSERT (NOW - MRD_chk >= tMRD)
+ REPORT "tMRD violation during Precharge"
+ SEVERITY WARNING;
+
+ -- Precharge Bank 0
+ IF ((Addr (10) = '1' OR (Addr (10) = '0' AND Ba = "00")) AND Act_b0 = '1') THEN
+ Act_b0 := '0';
+ Pc_b0 := '1';
+ RP_chk0 := NOW;
+
+ -- Activate to Precharge bank 0
+ ASSERT (NOW - RAS_chk0 >= tRAS)
+ REPORT "tRAS violation during Precharge"
+ SEVERITY WARNING;
+
+ -- tWR violation check for Write
+ ASSERT (NOW - WR_chk0 >= tWR)
+ REPORT "tWR violation during Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Precharge Bank 1
+ IF ((Addr (10) = '1' OR (Addr (10) = '0' AND Ba = "01")) AND Act_b1 = '1') THEN
+ Act_b1 := '0';
+ Pc_b1 := '1';
+ RP_chk1 := NOW;
+
+ -- Activate to Precharge
+ ASSERT (NOW - RAS_chk1 >= tRAS)
+ REPORT "tRAS violation during Precharge"
+ SEVERITY WARNING;
+
+ -- tWR violation check for Write
+ ASSERT (NOW - WR_chk1 >= tWR)
+ REPORT "tWR violation during Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Precharge Bank 2
+ IF ((Addr (10) = '1' OR (Addr (10) = '0' AND Ba = "10")) AND Act_b2 = '1') THEN
+ Act_b2 := '0';
+ Pc_b2 := '1';
+ RP_chk2 := NOW;
+
+ -- Activate to Precharge
+ ASSERT (NOW - RAS_chk2 >= tRAS)
+ REPORT "tRAS violation during Precharge"
+ SEVERITY WARNING;
+
+ -- tWR violation check for Write
+ ASSERT (NOW - WR_chk2 >= tWR)
+ REPORT "tWR violation during Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Precharge Bank 3
+ IF ((Addr (10) = '1' OR (Addr (10) = '0' AND Ba = "11")) AND Act_b3 = '1') THEN
+ Act_b3 := '0';
+ Pc_b3 := '1';
+ RP_chk3 := NOW;
+
+ -- Activate to Precharge
+ ASSERT (NOW - RAS_chk3 >= tRAS)
+ REPORT "tRAS violation during Precharge"
+ SEVERITY WARNING;
+
+ -- tWR violation check for Write
+ ASSERT (NOW - WR_chk3 >= tWR)
+ REPORT "tWR violation during Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Pipeline for READ
+ IF CAS_latency_15 = '1' THEN
+ A10_precharge (3) := Addr(10);
+ Bank_precharge (3) := Ba;
+ Cmnd_precharge (3) := '1';
+ ELSIF CAS_latency_2 = '1' THEN
+ A10_precharge (4) := Addr(10);
+ Bank_precharge (4) := Ba;
+ Cmnd_precharge (4) := '1';
+ ELSIF CAS_latency_25 = '1' THEN
+ A10_precharge (5) := Addr(10);
+ Bank_precharge (5) := Ba;
+ Cmnd_precharge (5) := '1';
+ ELSIF CAS_latency_3 = '1' THEN
+ A10_precharge (6) := Addr(10);
+ Bank_precharge (6) := Ba;
+ Cmnd_precharge (6) := '1';
+ ELSIF CAS_latency_4 = '1' THEN
+ A10_precharge (8) := Addr(10);
+ Bank_precharge (8) := Ba;
+ Cmnd_precharge (8) := '1';
+ END IF;
+ END IF;
+
+ -- Burst Terminate
+ IF Burst_term = '1' THEN
+ -- Pipeline for Read
+ IF CAS_latency_15 = '1' THEN
+ Cmnd_bst (3) := '1';
+ ELSIF CAS_latency_2 = '1' THEN
+ Cmnd_bst (4) := '1';
+ ELSIF CAS_latency_25 = '1' THEN
+ Cmnd_bst (5) := '1';
+ ELSIF CAS_latency_3 = '1' THEN
+ Cmnd_bst (6) := '1';
+ ELSIF CAS_latency_4 = '1' THEN
+ Cmnd_bst (8) := '1';
+ END IF;
+
+ -- Terminate Write
+ ASSERT (Data_in_enable = '0')
+ REPORT "It's illegal to Burst Terminate a Write"
+ SEVERITY WARNING;
+
+ -- Terminate Read with Auto Precharge
+ ASSERT (Read_precharge (0) = '0' AND Read_precharge (1) = '0' AND
+ Read_precharge (2) = '0' AND Read_precharge (3) = '0')
+ REPORT "It's illegal to Burst Terminate a Read with Auto Precharge"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Read Command
+ IF Read_enable = '1' THEN
+ -- CAS Latency Pipeline
+ IF Cas_latency_15 = '1' THEN
+ Read_cmnd (3) := '1';
+ Read_bank (3) := Ba;
+ Read_cols (3) := Addr (8 DOWNTO 0);
+ ELSIF Cas_latency_2 = '1' THEN
+ Read_cmnd (4) := '1';
+ Read_bank (4) := Ba;
+ Read_cols (4) := Addr (8 DOWNTO 0);
+ ELSIF Cas_latency_25 = '1' THEN
+ Read_cmnd (5) := '1';
+ Read_bank (5) := Ba;
+ Read_cols (5) := Addr (8 DOWNTO 0);
+ ELSIF Cas_latency_3 = '1' THEN
+ Read_cmnd (6) := '1';
+ Read_bank (6) := Ba;
+ Read_cols (6) := Addr (8 DOWNTO 0);
+ ELSIF Cas_latency_4 = '1' THEN
+ Read_cmnd (8) := '1';
+ Read_bank (8) := Ba;
+ Read_cols (8) := Addr (8 DOWNTO 0);
+ END IF;
+
+ -- Write to Read: Terminate Write Immediately
+ IF Data_in_enable = '1' THEN
+ Data_in_enable := '0';
+ END IF;
+
+ -- Interrupting a Read with Auto Precharge (same bank only)
+ ASSERT (Read_precharge(CONV_INTEGER(Ba)) = '0')
+ REPORT "It's illegal to interrupt a Read with Auto Precharge"
+ SEVERITY WARNING;
+
+ -- Activate to Read
+ ASSERT ((Ba = "00" AND Act_b0 = '1') OR
+ (Ba = "01" AND Act_b1 = '1') OR
+ (Ba = "10" AND Act_b2 = '1') OR
+ (Ba = "11" AND Act_b3 = '1'))
+ REPORT "Bank is not Activated for Read"
+ SEVERITY WARNING;
+
+ -- Activate to Read without Auto Precharge
+ IF Addr (10) = '0' THEN
+ ASSERT ((Ba = "00" AND NOW - RCD_chk0 >= tRCD) OR
+ (Ba = "01" AND NOW - RCD_chk1 >= tRCD) OR
+ (Ba = "10" AND NOW - RCD_chk2 >= tRCD) OR
+ (Ba = "11" AND NOW - RCD_chk3 >= tRCD))
+ REPORT "tRCD violation during Read"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Activate to Read with Auto Precharge
+ IF Addr (10) = '1' THEN
+ ASSERT ((Ba = "00" AND NOW - RAP_chk0 >= tRAP) OR
+ (Ba = "01" AND NOW - RAP_chk1 >= tRAP) OR
+ (Ba = "10" AND NOW - RAP_chk2 >= tRAP) OR
+ (Ba = "11" AND NOW - RAP_chk3 >= tRAP))
+ REPORT "tRAP violation during Read"
+ SEVERITY WARNING;
+ END IF;
+
+ -- Auto precharge
+ IF Addr (10) = '1' THEN
+ Read_precharge (Conv_INTEGER(Ba)) := '1';
+ Count_precharge (Conv_INTEGER(Ba)) := 0;
+ END IF;
+
+ -- DLL Check
+ IF (DLL_reset = '1') THEN
+ ASSERT (DLL_done = '1')
+ REPORT "DLL RESET not complete"
+ SEVERITY WARNING;
+ END IF;
+ END IF;
+
+ -- Write Command
+ IF Write_enable = '1' THEN
+ -- Pipeline for Write
+ Write_cmnd (2) := '1';
+ Write_bank (2) := Ba;
+ Write_cols (2) := Addr (8 DOWNTO 0);
+
+ -- Interrupting a Write with Auto Precharge (same bank only)
+ ASSERT (Write_precharge(CONV_INTEGER(Ba)) = '0')
+ REPORT "It's illegal to interrupt a Write with Auto Precharge"
+ SEVERITY WARNING;
+
+ -- Activate to Write
+ ASSERT ((Ba = "00" AND Act_b0 = '1') OR
+ (Ba = "01" AND Act_b1 = '1') OR
+ (Ba = "10" AND Act_b2 = '1') OR
+ (Ba = "11" AND Act_b3 = '1'))
+ REPORT "Bank is not Activated for Write"
+ SEVERITY WARNING;
+
+ -- Activate to Write
+ ASSERT ((Ba = "00" AND NOW - RCD_chk0 >= tRCD) OR
+ (Ba = "01" AND NOW - RCD_chk1 >= tRCD) OR
+ (Ba = "10" AND NOW - RCD_chk2 >= tRCD) OR
+ (Ba = "11" AND NOW - RCD_chk3 >= tRCD))
+ REPORT "tRCD violation during Write"
+ SEVERITY WARNING;
+
+ -- Auto precharge
+ IF Addr (10) = '1' THEN
+ Write_precharge (Conv_INTEGER(Ba)) := '1';
+ Count_precharge (Conv_INTEGER(Ba)) := 0;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+ --
+ -- Dqs Receiver
+ --
+ dqs_rcvrs : PROCESS
+ VARIABLE Dm_temp : STD_LOGIC_VECTOR (1 DOWNTO 0);
+ VARIABLE Dq_temp : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0);
+ BEGIN
+ WAIT ON Dqs;
+ -- Latch data at posedge Dqs
+ IF Dqs'EVENT AND Dqs (1) = '1' AND Dqs (0) = '1' THEN
+ Dq_temp := Dq;
+ Dm_temp := Dm;
+ END IF;
+ -- Latch data at negedge Dqs
+ IF Dqs'EVENT AND Dqs (1) = '0' AND Dqs (0) = '0' THEN
+ Dq_pair <= (Dq & Dq_temp);
+ Dm_pair <= (Dm & Dm_temp);
+ END IF;
+ END PROCESS;
+
+ --
+ -- Setup timing checks
+ --
+ Setup_check : PROCESS
+ BEGIN
+ WAIT ON Sys_clk;
+ IF Sys_clk'EVENT AND Sys_clk = '1' THEN
+ ASSERT(Cke'LAST_EVENT >= tIS)
+ REPORT "CKE Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Cs_n'LAST_EVENT >= tIS)
+ REPORT "CS# Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Cas_n'LAST_EVENT >= tIS)
+ REPORT "CAS# Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Ras_n'LAST_EVENT >= tIS)
+ REPORT "RAS# Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(We_n'LAST_EVENT >= tIS)
+ REPORT "WE# Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Addr'LAST_EVENT >= tIS)
+ REPORT "ADDR Setup time violation -- tIS"
+ SEVERITY WARNING;
+ ASSERT(Ba'LAST_EVENT >= tIS)
+ REPORT "BA Setup time violation -- tIS"
+ SEVERITY WARNING;
+ END IF;
+ END PROCESS;
+
+ --
+ -- Hold timing checks
+ --
+ Hold_check : PROCESS
+ BEGIN
+ WAIT ON Sys_clk'DELAYED (tIH);
+ IF Sys_clk'DELAYED (tIH) = '1' THEN
+ ASSERT(Cke'LAST_EVENT >= tIH)
+ REPORT "CKE Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Cs_n'LAST_EVENT >= tIH)
+ REPORT "CS# Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Cas_n'LAST_EVENT >= tIH)
+ REPORT "CAS# Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Ras_n'LAST_EVENT >= tIH)
+ REPORT "RAS# Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(We_n'LAST_EVENT >= tIH)
+ REPORT "WE# Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Addr'LAST_EVENT >= tIH)
+ REPORT "ADDR Hold time violation -- tIH"
+ SEVERITY WARNING;
+ ASSERT(Ba'LAST_EVENT >= tIH)
+ REPORT "BA Hold time violation -- tIH"
+ SEVERITY WARNING;
+ END IF;
+ END PROCESS;
+
+END behave;
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/reset_virtex4.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/reset_virtex4.vhd
new file mode 100644
index 0000000..4f799c5
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/reset_virtex4.vhd
@@ -0,0 +1,111 @@
+-------------------------------------------------------------------------
+-- Project: SDRAM controller
+-- This file: Reset generator (Virtex-4 specific)
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+Library UNISIM;
+use UNISIM.vcomponents.all;
+
+entity reset is
+ port
+ (
+ clk : in std_logic;
+ rst_in : in std_logic;
+ rst_out : out std_logic
+ );
+end;
+
+architecture tech of reset is
+
+ signal rst : std_logic;
+ signal shift_pipe : std_logic_vector(3 downto 0);
+ attribute KEEP : string;
+ attribute KEEP of shift_pipe : signal is "TRUE";
+
+begin
+
+ rst <= shift_pipe(0);
+
+bufg_reset: bufg
+ port map
+ (
+ o => rst_out,
+ i => rst
+ );
+
+fdp0: fdp
+ generic map
+ (
+ init => '1'
+ )
+ port map
+ (
+ d => rst_in,
+ c => clk,
+ pre => '0',
+ q => shift_pipe(3)
+ );
+
+fdp1: fdp
+ generic map
+ (
+ init => '1'
+ )
+ port map
+ (
+
+ d => shift_pipe(3),
+ c => clk,
+ pre => '0',
+ q => shift_pipe(2)
+ );
+
+fdp2: fdp
+ generic map
+ (
+ init => '1'
+ )
+ port map
+ (
+ d => shift_pipe(2),
+ c => clk,
+ pre => '0',
+ q => shift_pipe(1)
+ );
+
+fdp3: fdp
+ generic map
+ (
+ init => '1'
+ )
+ port map
+ (
+
+ d => shift_pipe(1),
+ c => clk,
+ pre => '0',
+ q => shift_pipe(0)
+ );
+
+end tech;
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd
new file mode 100644
index 0000000..a50b6e8
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd
@@ -0,0 +1,269 @@
+-------------------------------------------------------------------------
+-- Project: SDRAM controller
+-- This file: SDRAM command controller
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+use work.sdram_config.all;
+use work.sdram_types.all;
+
+entity sdram_cmd is
+ Generic (BL : natural := 2);
+ Port (
+ rst : in STD_LOGIC;
+ clk : in STD_LOGIC;
+ enable : in STD_LOGIC;
+ u_tag_in : in user_tag_t;
+ u_tag_out : out user_tag_t;
+ phy_ctrl : out phy_ctrl_t;
+ cmd : in sdr_cmd_t;
+ cmd_we : in STD_LOGIC;
+ cmd_ack : out STD_LOGIC;
+ col_addr : in col_addr_t;
+ mode_word : in mode_word_t;
+ sdr_cmd_ctrl : out sdr_cmd_lines_t;
+ sdr_addr : out sdr_addr_t;
+ sdr_ba : out sdr_ba_t
+ );
+end sdram_cmd;
+
+architecture behaviour of sdram_cmd is
+
+ signal st_sdr, st_sdr_next : sdr_state_t;
+
+ signal cc_preset : natural range 0 to 10;
+ signal cc_load_en : std_logic;
+ signal cycle_finished : std_logic;
+
+ signal burst_preset : natural range 0 to 3;
+ signal burst_load_en : std_logic;
+ signal burst_finished : std_logic;
+
+begin
+
+ u_tag_out <= u_tag_in;
+
+------------------------------------------------------------------------------------------
+
+fsm_sdr_state:
+ process (st_sdr, cmd, cmd_we, cycle_finished, burst_finished, mode_word, enable, col_addr)
+ begin
+ st_sdr_next <= st_sdr;
+ sdr_cmd_ctrl <= COMMAND(SD_NOP);
+
+ cc_load_en <= '0';
+ cc_preset <= TIMING(cmd);
+ burst_load_en <= '0';
+ cmd_ack <= '0';
+ burst_preset <= BL/2-1;
+ phy_ctrl.re <= '0';
+ phy_ctrl.drive_en <= '0';
+ phy_ctrl.we <= '0';
+ phy_ctrl.utag_we <= '0';
+ sdr_addr <= mode_word(sdr_addr_t'left downto sdr_addr_t'right);
+ sdr_ba <= mode_word(mode_word_t'left downto mode_word_t'left-1);
+
+ case st_sdr is
+ when PWR_DOWN =>
+ sdr_cmd_ctrl <= COMMAND(SD_DESELECT);
+ if enable = '1' then
+ st_sdr_next <= IDLE;
+ end if;
+
+ when PRECHARGE =>
+ if cycle_finished = '1' then
+ st_sdr_next <= IDLE;
+ end if;
+
+ when MODE =>
+ if cycle_finished = '1' then
+ st_sdr_next <= IDLE;
+ end if;
+
+ when IDLE =>
+ if cmd_we = '1' then
+ cmd_ack <= '1';
+ cc_load_en <= '1';
+ cc_preset <= TIMING(cmd);
+ sdr_cmd_ctrl <= COMMAND(cmd);
+ case cmd is
+ when SD_PRE =>
+ st_sdr_next <= PRECHARGE;
+ sdr_addr(BIT_PRE_ALL) <= mode_word(BIT_PRE_ALL);
+ when SD_LMR =>
+ st_sdr_next <= MODE;
+ when SD_ACT =>
+ st_sdr_next <= ROW_ACT;
+ when SD_AR =>
+ st_sdr_next <= AUTO_REF;
+ when others => null;
+ end case;
+ end if;
+
+ when ROW_ACT =>
+ if cycle_finished = '1' then
+ if cmd_we = '1' then
+ cmd_ack <= '1';
+ burst_load_en <= '1';
+ cc_load_en <= '1';
+ cc_preset <= TIMING(cmd);
+ sdr_cmd_ctrl <= COMMAND(cmd);
+ case cmd is
+ when SD_PRE =>
+ st_sdr_next <= PRECHARGE;
+ when SD_READ =>
+ phy_ctrl.utag_we <= '1';
+ st_sdr_next <= READ;
+ sdr_addr(col_addr_t'range) <= col_addr;
+ when SD_WRITE =>
+ phy_ctrl.utag_we <= '1';
+ phy_ctrl.drive_en <= '1';
+ st_sdr_next <= WRITE;
+ sdr_addr(col_addr_t'range) <= col_addr;
+ when others => null;
+ end case;
+ end if;
+ end if;
+
+ when WRITE =>
+ phy_ctrl.drive_en <= '1';
+ phy_ctrl.we <= '1';
+ if burst_finished = '1' then
+ if cmd_we = '1' and cmd = SD_WRITE then
+ sdr_addr(col_addr_t'range) <= col_addr;
+ cmd_ack <= '1';
+ burst_load_en <= '1';
+ sdr_cmd_ctrl <= COMMAND(cmd);
+ phy_ctrl.utag_we <= '1';
+ else
+ phy_ctrl.drive_en <= '0';
+ cc_load_en <= '1';
+ cc_preset <= TIMING(SD_WRITE)+1;
+ st_sdr_next <= ROW_ACT;
+ end if;
+ end if;
+
+ when READ =>
+ phy_ctrl.re <= '1';
+ if burst_finished = '1' then
+ if cmd_we = '1' and cmd = SD_READ then
+ sdr_addr(col_addr_t'range) <= col_addr;
+ cmd_ack <= '1';
+ burst_load_en <= '1';
+ sdr_cmd_ctrl <= COMMAND(cmd);
+ phy_ctrl.utag_we <= '1';
+ else
+ cc_load_en <= '1';
+ cc_preset <= TIMING(SD_READ);
+ st_sdr_next <= ROW_ACT;
+ end if;
+ end if;
+
+ when WRITE_A => -- not implemented yet
+ cmd_ack <= '1';
+ st_sdr_next <= IDLE;
+
+ when READ_A => -- not implemented yet
+ cmd_ack <= '1';
+ st_sdr_next <= IDLE;
+
+ when BURST_STOP => -- not implemented yet
+ cmd_ack <= '1';
+ st_sdr_next <= IDLE;
+
+ when SELF_REF => -- not implemented yet
+ cmd_ack <= '1';
+ st_sdr_next <= IDLE;
+
+ when PRE_PWR_DOWN => -- not implemented yet
+ cmd_ack <= '1';
+ st_sdr_next <= IDLE;
+
+ when ACT_PWR_DOWN => -- not implemented yet
+ cmd_ack <= '1';
+ st_sdr_next <= IDLE;
+
+ when AUTO_REF =>
+ if cycle_finished = '1' then
+ st_sdr_next <= IDLE;
+ end if;
+
+ when others =>
+ st_sdr_next <= IDLE;
+ end case;
+
+ end process;
+
+fsm_sdr_state_next:
+ process (rst, clk)
+ begin
+ if rst = '1' then
+ st_sdr <= PWR_DOWN;
+ elsif rising_edge(clk) then
+ st_sdr <= st_sdr_next;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+cycle_counter:
+ process (rst, clk)
+ variable cycle_cnt : natural range 0 to 10;
+ begin
+ if rst = '1' then
+ cycle_cnt := 0;
+ cycle_finished <= '0';
+ elsif rising_edge(clk) then
+ cycle_finished <= '0';
+ if cc_load_en = '1' then
+ cycle_cnt := cc_preset;
+ elsif cycle_cnt /= 0 then
+ cycle_cnt := cycle_cnt - 1;
+ else
+ cycle_finished <= '1';
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+burst_counter:
+ process (rst, clk)
+ variable burst_cnt : natural range 0 to 3;
+ begin
+ if rst = '1' then
+ burst_cnt := 0;
+ elsif rising_edge(clk) then
+ burst_finished <= '0';
+ if burst_load_en = '1' then
+ burst_cnt := burst_preset;
+ elsif burst_cnt /= 0 then
+ burst_cnt := burst_cnt - 1;
+ end if;
+ if burst_cnt = 0 then
+ burst_finished <= '1';
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+end behaviour;
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdram_config.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_config.vhd
new file mode 100644
index 0000000..b62e085
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_config.vhd
@@ -0,0 +1,74 @@
+-------------------------------------------------------------------------
+-- Project: SDRAM controller
+-- This file: User SDRAM component adjustments
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+
+package sdram_config is
+
+ constant DDR_DATA_WIDTH : positive := 16; -- External DDR-SDRAM Module data bus width
+ constant DDR_ADDR_WIDTH : positive := 13; -- number of address lines to DDR-SDRAM Device/Module
+ constant DDR_BANK_WIDTH : positive := 2; -- Number of BANK address lines of external DDR-SDRAM
+ constant DDR_ROW_ADDR_WIDTH : positive := 13; --
+ constant DDR_COL_ADDR_WIDTH : positive := 9; --
+
+ constant LMR_REG_BASE : natural := 0;
+ constant LMR_REG_EXTENDED : natural := 1;
+ constant LMR_OP_NORMAL : natural := 0;
+ constant LMR_OP_RES_DLL : natural := 2;
+ constant LMR_BT_SEQ : natural := 0;
+ constant LMR_BT_ILVD : natural := 1;
+ constant LMR_BL2 : natural := 1;
+ constant LMR_BL4 : natural := 2;
+ constant LMR_BL8 : natural := 3;
+ constant LMR_CL2 : natural := 2;
+ constant LMR_CL3 : natural := 3;
+ constant LMR_CL2_5 : natural := 6;
+
+ -- DDR SDRAM Hardware defined constants
+ constant BIT_AUTO_PRE : positive := 10; -- bit-position in column address for auto precharge (see Data Sheet)
+ constant BIT_PRE_ALL : positive := 10; -- bit-position in column address for precharge all (see Data Sheet)
+ constant ENABLE_PRE_ALL : std_logic := '1';
+ constant ENABLE_AUTO_PRE : std_logic := '0';
+
+ -- DDR-SDR TIMING constants ------------------------------------------------------------------
+ -- After REFRESH_CLOCKS a refresh cycle is necessary, 64ms / 8192 = max every 7.8125 us refesh
+ constant REFRESH_INTERVAL : real := 7.8125; -- us
+
+ -- These values are for your SDRAM part (see datasheet)
+ constant TCAS : positive := 2; -- CAS latency [clocks]
+ constant TRP : positive := 2; -- precharge command period
+ constant TRAS : positive := 4; -- active to precharge delay
+ constant TRFC : positive := 8; -- auto refresh command period
+ constant TMRD : positive := 2; -- load mode register command cylce time
+ constant TRCD : positive := 2; -- active to read or write delay !
+ constant TWR : positive := 2; -- write recovery time
+
+ constant PWR_UP_WAIT : natural := 1; -- µs
+
+ subtype user_tag_t is unsigned(3 downto 0);
+
+ ----------------------------------------------------------------------------------------------
+
+end sdram_config;
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl.vhd
new file mode 100644
index 0000000..dbb5b80
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl.vhd
@@ -0,0 +1,487 @@
+-------------------------------------------------------------------------
+-- Project: SDRAM controller
+-- This file: SDRAM main controller and user I/F
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+use work.sdram_config.all;
+use work.sdram_types.all;
+use work.utils_pkg.all;
+
+entity sdram_ctrl is
+ Generic
+ (
+ f_sysclk : natural := 100E6;
+ BL : natural := 2
+ );
+ Port (
+ rst : in STD_LOGIC;
+ clk : in STD_LOGIC;
+ u_busy : out STD_LOGIC;
+ u_tag_in : in user_tag_t;
+ u_tag_out : out user_tag_t;
+ u_addr : in user_addr_t;
+ u_cmd : in user_cmd_t;
+ u_cmd_we : in STD_LOGIC;
+ col_addr : out col_addr_t;
+ sdr_cmd_busy : in STD_LOGIC;
+ sdr_cmd : out sdr_cmd_t;
+ sdr_cmd_we : out STD_LOGIC;
+ sdr_mode : out mode_word_t;
+ sdr_cke : out STD_LOGIC
+ );
+end sdram_ctrl;
+
+architecture behaviour of sdram_ctrl is
+
+ constant LMR_BURST_LEN : natural := NextExpBaseTwo(BL);
+
+ type ctrl_state_t is (RESET, POWER_WAIT, INIT, INIT_WAIT, USER_READY, USER_WRITE_PRE, USER_WRITE_ACT, USER_WRITE, USER_READ_PRE, USER_READ_ACT, USER_READ, REFRESH);
+ signal st_ctrl, st_ctrl_next : ctrl_state_t;
+
+ constant PWR_UP_CLOCK_INTERVAL : natural := PWR_UP_WAIT*(f_sysclk/1E6);
+ signal pwr_up_cnt : natural range 0 to PWR_UP_CLOCK_INTERVAL-1;
+ signal pwr_up_cnt_rst : std_logic;
+ signal pwr_up_finished : std_logic;
+
+ signal cycle_cnt : natural range 0 to 255;
+ signal cc_preset : natural range 0 to 255;
+ signal cc_load_en : std_logic;
+ signal cycle_finished : std_logic;
+
+ signal seq_cnt : natural range 0 to 31;
+ signal seq_rst_en : std_logic;
+ signal seq_cnt_en : std_logic;
+
+ constant REFRESH_CLOCK_INTERVAL : natural := natural(REFRESH_INTERVAL*real(f_sysclk)/1.0E6);
+ signal refresh_cnt : natural range 0 to REFRESH_CLOCK_INTERVAL-1;
+ signal refresh_request : std_logic;
+ signal refresh_cnt_rst : std_logic;
+
+ signal addr_reg_load_en : std_logic;
+
+ signal u_tag_reg : user_tag_t;
+ signal bank_addr_reg : bank_addr_t;
+ signal row_addr_reg : row_addr_t;
+ signal col_addr_reg : col_addr_t;
+
+ signal u_bank_addr : bank_addr_t;
+ signal u_row_addr : row_addr_t;
+ signal u_col_addr : col_addr_t;
+
+ signal act_request : std_logic;
+ signal act_request_set : std_logic;
+ signal act_request_clr : std_logic;
+
+ type init_seq_rom_t is array (0 to 14) of init_seq_t;
+
+ constant init_seq_rom : init_seq_rom_t :=
+ (
+ (
+ cmd => SD_NOP,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_PRE,
+ mode_word => "000010000000000",
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_NOP,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_LMR,
+ mode_word => to_unsigned(LMR_REG_EXTENDED, 2) & "0000000000010",
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_NOP,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_LMR,
+ mode_word => to_unsigned(LMR_REG_BASE, 2) & to_unsigned(LMR_OP_RES_DLL, 6) & to_unsigned(LMR_CL2, 3) & '0' & to_unsigned(LMR_BURST_LEN, 3),
+ wait_cycle => 200
+ ),
+ (
+ cmd => SD_NOP,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_PRE,
+ mode_word => "000010000000000",
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_NOP,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_AR,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_NOP,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_AR,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_NOP,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ ),
+ (
+ cmd => SD_LMR,
+ mode_word => to_unsigned(LMR_REG_BASE, 2) & to_unsigned(LMR_OP_NORMAL, 6) & to_unsigned(LMR_CL2, 3) & '0' & to_unsigned(LMR_BURST_LEN, 3),
+ wait_cycle => 200
+ ),
+ (
+ cmd => SD_NOP,
+ mode_word => (others => '0'),
+ wait_cycle => 0
+ )
+
+ );
+
+begin
+
+ u_row_addr <= u_addr(user_addr_t'left downto user_addr_t'left-row_addr_t'length+1);
+ u_bank_addr <= u_addr(user_addr_t'left-row_addr_t'length downto user_addr_t'left-row_addr_t'length-bank_addr_t'length+1);
+ u_col_addr <= u_addr(user_addr_t'left-row_addr_t'length-bank_addr_t'length downto 0);
+
+------------------------------------------------------------------------------------------
+fsm_ctrl_state:
+ process (st_ctrl, u_tag_in, u_tag_reg, u_cmd, u_cmd_we, sdr_cmd_busy, pwr_up_finished, seq_cnt, cycle_finished, u_bank_addr, u_row_addr, bank_addr_reg, row_addr_reg, u_col_addr, col_addr_reg, refresh_request, act_request)
+ begin
+
+ u_busy <= '1';
+ pwr_up_cnt_rst <= '0';
+ cc_preset <= init_seq_rom(seq_cnt).wait_cycle;
+ cc_load_en <= '0';
+ sdr_cmd <= init_seq_rom(seq_cnt).cmd;
+ sdr_cmd_we <= '0';
+ sdr_mode <= bank_addr_reg & row_addr_reg;
+ col_addr <= col_addr_reg;
+ sdr_cke <= '1';
+ seq_cnt_en <= '0';
+ seq_rst_en <= '0';
+ addr_reg_load_en <= '0';
+ refresh_cnt_rst <= '0';
+ act_request_set <= '0';
+ act_request_clr <= '0';
+ u_tag_out <= u_tag_reg;
+
+ st_ctrl_next <= st_ctrl;
+ case st_ctrl is
+ when RESET =>
+ sdr_cke <= '0';
+ pwr_up_cnt_rst <= '1';
+ st_ctrl_next <= POWER_WAIT;
+
+ when POWER_WAIT =>
+ sdr_cke <= '0';
+ if pwr_up_finished = '1' then
+ seq_rst_en <= '1';
+ st_ctrl_next <= INIT;
+ end if;
+
+ when INIT =>
+ sdr_mode <= init_seq_rom(seq_cnt).mode_word;
+ sdr_cmd <= init_seq_rom(seq_cnt).cmd;
+ cc_preset <= init_seq_rom(seq_cnt).wait_cycle;
+ if seq_cnt = init_seq_rom_t'high then
+ act_request_set <= '1';
+ refresh_cnt_rst <= '1';
+ st_ctrl_next <= USER_READY;
+ elsif sdr_cmd_busy = '0' then
+ cc_load_en <= '1';
+ sdr_cmd_we <= '1';
+ st_ctrl_next <= INIT_WAIT;
+ end if;
+
+ when INIT_WAIT =>
+ if sdr_cmd_busy = '0' and cycle_finished = '1' then
+ seq_cnt_en <= '1';
+ st_ctrl_next <= INIT;
+ end if;
+
+ when USER_READY =>
+ if sdr_cmd_busy = '0' then
+ if refresh_request = '1' then
+ sdr_mode(BIT_PRE_ALL) <= '1';
+ sdr_cmd_we <= '1';
+ sdr_cmd <= SD_PRE;
+ st_ctrl_next <= REFRESH;
+ else
+ u_busy <= '0';
+ if u_cmd_we = '1' then
+ case u_cmd is
+ when UCMD_NOP =>
+ sdr_cmd <= SD_NOP;
+ when UCMD_LMR =>
+ sdr_cmd <= SD_NOP;
+ when UCMD_WRITE =>
+ col_addr <= u_col_addr;
+ u_tag_out <= u_tag_in;
+ sdr_mode(BIT_AUTO_PRE) <= ENABLE_AUTO_PRE;
+ addr_reg_load_en <= '1';
+ act_request_clr <= '1';
+ sdr_cmd <= SD_WRITE;
+ if (u_row_addr /= row_addr_reg) or act_request = '1' then
+ st_ctrl_next <= USER_WRITE_PRE;
+ elsif (u_bank_addr /= bank_addr_reg) then
+ if ENABLE_PRE_ALL = '1' then
+ st_ctrl_next <= USER_WRITE_ACT;
+ else
+ st_ctrl_next <= USER_WRITE_PRE;
+ end if;
+ elsif sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ else
+ st_ctrl_next <= USER_WRITE;
+ end if;
+ when UCMD_READ =>
+ col_addr <= u_col_addr;
+ u_tag_out <= u_tag_in;
+ sdr_mode(BIT_AUTO_PRE) <= ENABLE_AUTO_PRE;
+ addr_reg_load_en <= '1';
+ act_request_clr <= '1';
+ sdr_cmd <= SD_READ;
+ if (u_row_addr /= row_addr_reg) or act_request = '1' then
+ st_ctrl_next <= USER_READ_PRE;
+ elsif (u_bank_addr /= bank_addr_reg) then
+ if ENABLE_PRE_ALL = '1' then
+ st_ctrl_next <= USER_READ_ACT;
+ else
+ st_ctrl_next <= USER_READ_PRE;
+ end if;
+ elsif sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ else
+ st_ctrl_next <= USER_READ;
+ end if;
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end if;
+
+ when USER_WRITE_PRE =>
+ sdr_cmd <= SD_PRE;
+ sdr_mode(BIT_PRE_ALL) <= ENABLE_PRE_ALL;
+ if sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ st_ctrl_next <= USER_WRITE_ACT;
+ end if;
+
+ when USER_WRITE_ACT =>
+ sdr_cmd <= SD_ACT;
+ if sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ st_ctrl_next <= USER_WRITE;
+ end if;
+
+ when USER_WRITE =>
+ sdr_cmd <= SD_WRITE;
+ sdr_mode(BIT_AUTO_PRE) <= ENABLE_AUTO_PRE;
+ if sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ st_ctrl_next <= USER_READY;
+ end if;
+
+ when USER_READ_PRE =>
+ sdr_cmd <= SD_PRE;
+ sdr_mode(BIT_PRE_ALL) <= ENABLE_PRE_ALL;
+ if sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ st_ctrl_next <= USER_READ_ACT;
+ end if;
+
+ when USER_READ_ACT =>
+ sdr_cmd <= SD_ACT;
+ if sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ st_ctrl_next <= USER_READ;
+ end if;
+
+ when USER_READ =>
+ sdr_cmd <= SD_READ;
+ sdr_mode(BIT_AUTO_PRE) <= ENABLE_AUTO_PRE;
+ if sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ st_ctrl_next <= USER_READY;
+ end if;
+
+ when REFRESH =>
+ sdr_cmd <= SD_AR;
+ if sdr_cmd_busy = '0' then
+ sdr_cmd_we <= '1';
+ st_ctrl_next <= USER_READY;
+ refresh_cnt_rst <= '1';
+ act_request_set <= '1';
+ end if;
+
+ when others =>
+ st_ctrl_next <= RESET;
+ end case;
+
+ end process;
+
+fsm_ctrl_state_next:
+ process (rst, clk)
+ begin
+ if rst = '1' then
+ st_ctrl <= RESET;
+ elsif rising_edge(clk) then
+ st_ctrl <= st_ctrl_next;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+act_request_register:
+ process (rst, clk)
+ begin
+ if rst = '1' then
+ act_request <= '1';
+ elsif rising_edge(clk) then
+ if act_request_set = '1' then
+ act_request <= '1';
+ elsif act_request_clr = '1' then
+ act_request <= '0';
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+user_addr_register:
+ process (rst, clk)
+ begin
+ if rst = '1' then
+ bank_addr_reg <= (others => '0');
+ row_addr_reg <= (others => '0');
+ col_addr_reg <= (others => '0');
+ u_tag_reg <= (others => '0');
+ elsif rising_edge(clk) then
+ if addr_reg_load_en = '1' then
+ bank_addr_reg <= u_bank_addr;
+ row_addr_reg <= u_row_addr;
+ col_addr_reg <= u_col_addr;
+ u_tag_reg <= u_tag_in;
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+power_up_counter:
+ process (rst, clk)
+ begin
+ if rst = '1' then
+ pwr_up_cnt <= 0;
+ pwr_up_finished <= '0';
+ elsif rising_edge(clk) then
+ pwr_up_finished <= '0';
+ if pwr_up_cnt_rst = '1' then
+ pwr_up_cnt <= PWR_UP_CLOCK_INTERVAL-1;
+ else
+ if pwr_up_cnt /= 0 then
+ pwr_up_cnt <= pwr_up_cnt - 1;
+ else
+ pwr_up_finished <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+------------------------------------------------------------------------------------------
+refresh_counter:
+ process (rst, clk)
+ begin
+ if rst = '1' then
+ refresh_cnt <= 0;
+ refresh_request <= '0';
+ elsif rising_edge(clk) then
+ refresh_request <= '0';
+ if refresh_cnt_rst = '1' then
+ refresh_cnt <= REFRESH_CLOCK_INTERVAL-1;
+ else
+ if refresh_cnt /= 0 then
+ refresh_cnt <= refresh_cnt - 1;
+ else
+ refresh_request <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+cycle_counter:
+ process (rst, clk)
+ begin
+ if rst = '1' then
+ cycle_cnt <= 0;
+ cycle_finished <= '0';
+ elsif rising_edge(clk) then
+ cycle_finished <= '0';
+ if cc_load_en = '1' then
+ cycle_cnt <= cc_preset;
+ elsif cycle_cnt /= 0 then
+ cycle_cnt <= cycle_cnt - 1;
+ else
+ cycle_finished <= '1';
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+seq_counter:
+ process (rst, clk)
+ begin
+ if rst = '1' then
+ seq_cnt <= 0;
+ elsif rising_edge(clk) then
+ if seq_rst_en = '1' then
+ seq_cnt <= 0;
+ elsif seq_cnt_en = '1' then
+ if seq_cnt /= init_seq_rom_t'high then
+ seq_cnt <= seq_cnt + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+end behaviour;
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd
new file mode 100644
index 0000000..3a9aee5
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd
@@ -0,0 +1,283 @@
+-------------------------------------------------------------------------
+-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
+-- This file: cpu_embedded using cpu_core and rom
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+use work.fifo_ctrl_pkg.all;
+use work.sdram_config.all;
+use work.sdram_types.all;
+
+entity sdram_ctrl_frontend_wb is
+ Generic
+ (
+ BL : natural := 2;
+ f_sysclk : natural := 100E6;
+ fifo_depth : integer := 4
+ );
+ Port
+ (
+ RST_I : in STD_LOGIC;
+ CLK_I : in STD_LOGIC;
+ CLK270_I : in STD_LOGIC;
+ CLK270VAR_I : in STD_LOGIC;
+
+ CYC_I : in STD_LOGIC;
+ STB_I : in STD_LOGIC;
+ SEL_I : in unsigned(3 downto 0);
+ WE_I : in STD_LOGIC;
+ ACK_O : out STD_LOGIC;
+ RDY_O : out STD_LOGIC;
+ ADDR_I : in unsigned(31 downto 0);
+ DAT_I : in unsigned(31 downto 0);
+ DAT_O : out unsigned(31 downto 0);
+
+ -- SDRAM signals
+ sd_clk_p : out STD_LOGIC;
+ sd_clk_n : out STD_LOGIC;
+ sd_cke : out STD_LOGIC;
+ sd_cs_n : out STD_LOGIC;
+ sd_cas_n : out STD_LOGIC;
+ sd_ras_n : out STD_LOGIC;
+ sd_we_n : out STD_LOGIC;
+ sd_addr : out sdr_addr_t;
+ sd_ba : out sdr_ba_t;
+ sd_dm : out unsigned(DDR_DM_WIDTH-1 downto 0);
+ sd_dqs : inout unsigned(DDR_DQS_WIDTH-1 downto 0);
+ sd_data : inout unsigned(DDR_DATA_WIDTH-1 downto 0)
+
+ );
+end sdram_ctrl_frontend_wb;
+
+architecture struct of sdram_ctrl_frontend_wb is
+
+ -- Number of user data words for simulation
+ signal u_addr : user_addr_t;
+ signal u_tag_in : user_tag_t;
+ signal u_tag_rd : user_tag_t;
+ signal u_tag_wr : user_tag_t;
+ signal u_cmd : user_cmd_t;
+ signal u_cmd_we : std_logic;
+ signal u_busy : std_logic;
+ signal u_data_w : unsigned(SDR_DATA_WIDTH-1 downto 0);
+ signal u_dm_wr_in : unsigned(SDR_DM_WIDTH-1 downto 0);
+ signal u_dm_rd_in : unsigned(SDR_DM_WIDTH-1 downto 0);
+ signal u_dm_rd_out : unsigned(SDR_DM_WIDTH-1 downto 0);
+ signal u_data_r : unsigned(SDR_DATA_WIDTH-1 downto 0);
+ signal u_data_vld : std_logic;
+ signal u_req_wr : std_logic;
+ signal rdy : std_logic;
+
+ constant CAT_FIFO_WIDTH : integer := user_cmd_t'length + user_tag_t'length + DDR_ROW_ADDR_WIDTH + DDR_BANK_WIDTH + DDR_COL_ADDR_WIDTH + SDR_DM_WIDTH;
+ signal cat_fifo_din : unsigned(CAT_FIFO_WIDTH-1 downto 0);
+ signal cat_fifo_dout : unsigned(CAT_FIFO_WIDTH-1 downto 0);
+ signal cat_fifo_re : std_logic;
+ signal cat_fifo_we : std_logic;
+ signal cat_fifo_full : std_logic;
+ signal cat_fifo_empty : std_logic;
+-- signal cat_fifo_almost_full : std_logic;
+-- signal cat_fifo_almost_empty : std_logic;
+
+ signal write_fifo_din : unsigned(SDR_DATA_WIDTH+SDR_DM_WIDTH-1 downto 0);
+ signal write_fifo_dout : unsigned(SDR_DATA_WIDTH+SDR_DM_WIDTH-1 downto 0);
+ signal write_fifo_re : std_logic;
+ signal write_fifo_we : std_logic;
+ signal write_fifo_full : std_logic;
+ signal write_fifo_empty : std_logic;
+-- signal write_fifo_almost_full : std_logic;
+-- signal write_fifo_almost_empty : std_logic;
+
+ signal read_fifo_din : unsigned(SDR_DATA_WIDTH+SDR_DM_WIDTH-1 downto 0);
+ signal read_fifo_dout : unsigned(SDR_DATA_WIDTH+SDR_DM_WIDTH-1 downto 0);
+ signal read_fifo_re : std_logic;
+ signal read_fifo_we : std_logic;
+ signal read_fifo_full : std_logic;
+ signal read_fifo_empty : std_logic;
+-- signal read_fifo_almost_full : std_logic;
+-- signal read_fifo_almost_empty : std_logic;
+
+ alias cmd_fifo_in is cat_fifo_din(CAT_FIFO_WIDTH-1 downto CAT_FIFO_WIDTH-user_cmd_t'length);
+ alias tag_fifo_in is cat_fifo_din(CAT_FIFO_WIDTH-user_cmd_t'length-1 downto CAT_FIFO_WIDTH-user_cmd_t'length-user_tag_t'length);
+ alias addr_fifo_in is cat_fifo_din(CAT_FIFO_WIDTH-user_cmd_t'length-user_tag_t'length-1 downto SDR_DM_WIDTH);
+ alias dm_rd_fifo_in is cat_fifo_din(SDR_DM_WIDTH-1 downto 0);
+ alias cmd_fifo_out is cat_fifo_dout(CAT_FIFO_WIDTH-1 downto CAT_FIFO_WIDTH-user_cmd_t'length);
+ alias tag_fifo_out is cat_fifo_dout(CAT_FIFO_WIDTH-user_cmd_t'length-1 downto CAT_FIFO_WIDTH-user_cmd_t'length-user_tag_t'length);
+ alias addr_fifo_out is cat_fifo_dout(CAT_FIFO_WIDTH-user_cmd_t'length-user_tag_t'length-1 downto SDR_DM_WIDTH);
+ alias dm_rd_fifo_out is cat_fifo_dout(SDR_DM_WIDTH-1 downto 0);
+
+ alias write_fifo_dm_in is write_fifo_din(write_fifo_din'length-1 downto write_fifo_din'length-SDR_DM_WIDTH);
+ alias write_fifo_data_in is write_fifo_din(write_fifo_din'length-SDR_DM_WIDTH-1 downto 0);
+ alias write_fifo_dm_out is write_fifo_dout(write_fifo_dout'length-1 downto write_fifo_dout'length-SDR_DM_WIDTH);
+ alias write_fifo_data_out is write_fifo_dout(write_fifo_dout'length-SDR_DM_WIDTH-1 downto 0);
+
+ alias read_fifo_dm_in is read_fifo_din(read_fifo_din'length-1 downto read_fifo_din'length-SDR_DM_WIDTH);
+ alias read_fifo_data_in is read_fifo_din(read_fifo_din'length-SDR_DM_WIDTH-1 downto 0);
+ alias read_fifo_dm_out is read_fifo_dout(read_fifo_dout'length-1 downto read_fifo_dout'length-SDR_DM_WIDTH);
+ alias read_fifo_data_out is read_fifo_dout(read_fifo_dout'length-SDR_DM_WIDTH-1 downto 0);
+
+begin
+
+ -- Instantiate synchronous FIFO
+ inst_cat_fifo: entity work.fifo_sync
+ GENERIC MAP
+ (
+ addr_width => fifo_depth,
+ data_width => CAT_FIFO_WIDTH
+ )
+ PORT MAP
+ (
+ rst => RST_I,
+ clk => CLK_I,
+ we => cat_fifo_we,
+ re => cat_fifo_re,
+ fifo_full => cat_fifo_full,
+ fifo_empty => cat_fifo_empty,
+ fifo_afull => open,
+ fifo_aempty => open,
+ data_w => cat_fifo_din,
+ data_r => cat_fifo_dout
+ );
+
+ -- Instantiate synchronous FIFO
+ inst_write_fifo: entity work.fifo_sync
+ GENERIC MAP
+ (
+ addr_width => fifo_depth,
+ data_width => 2*DDR_DATA_WIDTH + SDR_DM_WIDTH
+ )
+ PORT MAP
+ (
+ rst => RST_I,
+ clk => CLK_I,
+ we => write_fifo_we,
+ re => write_fifo_re,
+ fifo_full => write_fifo_full,
+ fifo_empty => write_fifo_empty,
+ fifo_afull => open,
+ fifo_aempty => open,
+ data_w => write_fifo_din,
+ data_r => write_fifo_dout
+ );
+
+ -- Instantiate synchronous FIFO
+ inst_read_fifo: entity work.fifo_sync
+ GENERIC MAP
+ (
+ addr_width => fifo_depth,
+ data_width => 2*DDR_DATA_WIDTH + SDR_DM_WIDTH
+ )
+ PORT MAP
+ (
+ rst => RST_I,
+ clk => CLK_I,
+ we => read_fifo_we,
+ re => read_fifo_re,
+ fifo_full => read_fifo_full,
+ fifo_empty => read_fifo_empty,
+ fifo_afull => open,
+ fifo_aempty => open,
+ data_w => read_fifo_din,
+ data_r => read_fifo_dout
+ );
+
+ -- DDR SDRAM Controller Core
+ inst_sdram_ctrl : entity work.sdram_ctrl_top
+ Generic map
+ (
+ BL => BL,
+ f_sysclk => f_sysclk
+ )
+ Port map
+ (
+
+ sys_rst_in => RST_I,
+ sys_clk0_in => CLK_I,
+
+ sys_clk270_in => CLK270_I,
+ capture_clk270_in => CLK270VAR_I,
+
+ -- User interface
+ u_data_vld => u_data_vld,
+ u_data_req_w => u_req_wr,
+ u_data_req_r => open,
+ u_tag_in => u_tag_in,
+ u_tag_rd => u_tag_rd,
+ u_tag_wr => u_tag_wr,
+ u_busy => u_busy,
+ u_addr => u_addr,
+ u_cmd => u_cmd,
+ u_cmd_we => u_cmd_we,
+ u_data_wr => u_data_w,
+ u_data_rd => u_data_r,
+ u_dm_wr_in => u_dm_wr_in,
+ u_dm_rd_in => u_dm_rd_in,
+ u_dm_rd_out => u_dm_rd_out,
+
+ -- SDRAM signals
+ sd_clk_p => sd_clk_p,
+ sd_clk_n => sd_clk_n,
+ sd_cke => sd_cke,
+ sd_cs_n => sd_cs_n,
+ sd_cas_n => sd_cas_n,
+ sd_ras_n => sd_ras_n,
+ sd_we_n => sd_we_n,
+ sd_addr => sd_addr,
+ sd_ba => sd_ba,
+ sd_dm => sd_dm,
+ sd_dqs => sd_dqs,
+ sd_data => sd_data
+
+ );
+
+------------------------------------------------------------------------------------------
+ RDY_O <= rdy and CYC_I;
+ rdy <= not (cat_fifo_full or write_fifo_full or read_fifo_full);
+ write_fifo_we <= STB_I and CYC_I and WE_I and rdy;
+ write_fifo_data_in <= DAT_I;
+ write_fifo_dm_in <= not SEL_I;
+ cat_fifo_we <= STB_I and CYC_I and rdy;
+ cmd_fifo_in <= UCMD_WRITE when WE_I = '1' else UCMD_READ;
+ addr_fifo_in <= ADDR_I(user_addr_t'range);
+ dm_rd_fifo_in <= not SEL_I;
+ tag_fifo_in <= (others=>'0');
+ DAT_O <= read_fifo_data_out;
+ ACK_O <= write_fifo_we or (CYC_I and not (WE_I or read_fifo_empty));
+
+ u_cmd_we <= (not cat_fifo_empty) and (not u_busy);
+ u_cmd <= cmd_fifo_out;
+ u_addr <= addr_fifo_out;
+ u_dm_rd_in <= dm_rd_fifo_out;
+ u_dm_wr_in <= write_fifo_dm_out;
+ u_tag_in <= tag_fifo_out;
+
+ write_fifo_re <= u_req_wr and (not write_fifo_empty);
+ cat_fifo_re <= u_cmd_we;
+ u_data_w <= write_fifo_data_out;
+ read_fifo_re <= (not read_fifo_empty); -- and dout_re;
+ read_fifo_we <= u_data_vld;
+ read_fifo_data_in <= u_data_r;
+ read_fifo_dm_in <= u_dm_rd_out;
+
+
+end architecture struct;
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd
new file mode 100644
index 0000000..f742f83
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd
@@ -0,0 +1,248 @@
+-------------------------------------------------------------------------
+-- Project: SDRAM controller
+-- This file: Top-level put all together
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+use work.sdram_config.all;
+use work.sdram_types.all;
+
+entity sdram_ctrl_top is
+ Generic
+ (
+ BL : natural := 2;
+ f_sysclk : natural := 100E6
+ );
+ Port
+ (
+ sys_rst_in : in STD_LOGIC;
+ sys_clk0_in : in STD_LOGIC;
+ sys_clk270_in : in STD_LOGIC;
+ capture_clk270_in : in STD_LOGIC;
+
+ -- User interface
+ u_data_vld : out STD_LOGIC;
+ u_data_req_w : out STD_LOGIC;
+ u_data_req_r : out STD_LOGIC;
+ u_busy : out STD_LOGIC;
+ u_tag_in : in user_tag_t;
+ u_tag_rd : out user_tag_t;
+ u_tag_wr : out user_tag_t;
+ u_addr : in user_addr_t;
+ u_cmd : in user_cmd_t;
+ u_cmd_we : in STD_LOGIC;
+ u_data_wr : in unsigned(SDR_DATA_WIDTH-1 downto 0);
+ u_dm_wr_in : in unsigned(SDR_DM_WIDTH-1 downto 0);
+ u_dm_rd_in : in unsigned(SDR_DM_WIDTH-1 downto 0);
+ u_dm_rd_out : out unsigned(SDR_DM_WIDTH-1 downto 0);
+ u_data_rd : out unsigned(SDR_DATA_WIDTH-1 downto 0);
+
+ -- SDRAM signals
+ sd_clk_p : out STD_LOGIC;
+ sd_clk_n : out STD_LOGIC;
+ sd_cke : out STD_LOGIC;
+ sd_cs_n : out STD_LOGIC;
+ sd_cas_n : out STD_LOGIC;
+ sd_ras_n : out STD_LOGIC;
+ sd_we_n : out STD_LOGIC;
+ sd_addr : out sdr_addr_t;
+ sd_ba : out sdr_ba_t;
+ sd_dm : out unsigned(DDR_DM_WIDTH-1 downto 0);
+ sd_dqs : inout unsigned(DDR_DQS_WIDTH-1 downto 0);
+ sd_data : inout unsigned(DDR_DATA_WIDTH-1 downto 0)
+
+ );
+end sdram_ctrl_top;
+
+architecture rtl of sdram_ctrl_top is
+
+
+ signal phy_ctrl : phy_ctrl_t;
+
+ signal u_tag : user_tag_t;
+ signal sd_cmd_in : sdr_cmd_t;
+ signal sd_cmd : sdr_cmd_t;
+ signal sd_cmd_we : std_logic;
+ signal cmd_ctrl : sdr_cmd_lines_t;
+ signal cke : std_logic;
+ signal ba : unsigned(DDR_BANK_WIDTH-1 downto 0);
+ signal addr : unsigned(DDR_ADDR_WIDTH-1 downto 0);
+
+ -- Clock generator
+
+ signal ctrl_rst : std_logic;
+ signal part_ctrl : part_ctrl_t;
+
+ -- SD command FIFO
+
+ constant CMD_FIFO_ADDR_WIDTH : positive := 2;
+ constant CMD_FIFO_DATA_WIDTH : positive := user_tag_t'length + 4 + mode_word_t'length + col_addr_t'length;
+ signal cmd_fifo_din : unsigned(CMD_FIFO_DATA_WIDTH-1 downto 0);
+ signal cmd_fifo_dout : unsigned(CMD_FIFO_DATA_WIDTH-1 downto 0);
+ signal cmd_fifo_re : std_logic;
+ signal cmd_fifo_we : std_logic;
+ signal cmd_fifo_full : std_logic;
+ signal cmd_fifo_empty : std_logic;
+
+ alias tag_fifo_in is cmd_fifo_din(CMD_FIFO_DATA_WIDTH-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length);
+ alias cmd_fifo_in is cmd_fifo_din(CMD_FIFO_DATA_WIDTH-user_tag_t'length-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length-4);
+ alias mode_fifo_in is cmd_fifo_din(CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-mode_word_t'length);
+ alias col_fifo_in is cmd_fifo_din(CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-mode_word_t'length-1 downto 0);
+
+ alias tag_fifo_out is cmd_fifo_dout(CMD_FIFO_DATA_WIDTH-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length);
+ alias cmd_fifo_out is cmd_fifo_dout(CMD_FIFO_DATA_WIDTH-user_tag_t'length-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length-4);
+ alias mode_fifo_out is cmd_fifo_dout(CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-1 downto CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-mode_word_t'length);
+ alias col_fifo_out is cmd_fifo_dout(CMD_FIFO_DATA_WIDTH-user_tag_t'length-4-mode_word_t'length-1 downto 0);
+
+begin
+
+ ---------------------------------
+ part_ctrl.cmd <= cmd_ctrl;
+ part_ctrl.ba <= ba;
+ part_ctrl.addr <= addr;
+ part_ctrl.cke <= cke;
+
+ ---------------------------------
+ sd_cmd_we <= not cmd_fifo_empty;
+ cmd_fifo_in <= to_unsigned(sd_cmd_in, 4);
+ sd_cmd <= sdr_cmd_t(to_integer(cmd_fifo_out));
+
+ ---------------------------------
+ inst_reset: entity work.reset
+ port map
+ (
+ clk => sys_clk0_in,
+ rst_in => sys_rst_in,
+ rst_out => ctrl_rst
+ );
+
+ -- Main controller
+ inst_sdram_ctrl : entity work.sdram_ctrl
+ Generic map
+ (
+ f_sysclk => 100E6,
+ BL => BL
+ )
+ Port map
+ (
+ rst => ctrl_rst,
+ clk => sys_clk0_in,
+ u_busy => u_busy,
+ u_tag_in => u_tag_in,
+ u_tag_out => tag_fifo_in,
+ u_cmd => u_cmd,
+ u_cmd_we => u_cmd_we,
+ u_addr => u_addr,
+ sdr_cmd_busy => cmd_fifo_full,
+ sdr_cmd => sd_cmd_in,
+ sdr_cmd_we => cmd_fifo_we,
+ col_addr => col_fifo_in,
+ sdr_mode => mode_fifo_in,
+ sdr_cke => cke
+ );
+
+ -- Instantiate synchronous FIFO
+ inst_sd_cmd_fifo: entity work.fifo_sync
+ GENERIC MAP
+ (
+ addr_width => CMD_FIFO_ADDR_WIDTH,
+ data_width => CMD_FIFO_DATA_WIDTH,
+ almost_full_thresh => 2**(CMD_FIFO_ADDR_WIDTH-1),
+ almost_empty_thresh => 2**(CMD_FIFO_ADDR_WIDTH-1)
+ )
+ PORT MAP
+ (
+ rst => ctrl_rst,
+ clk => sys_clk0_in,
+ we => cmd_fifo_we,
+ re => cmd_fifo_re,
+ fifo_full => cmd_fifo_full,
+ fifo_empty => cmd_fifo_empty,
+ fifo_afull => open,
+ fifo_aempty => open,
+ data_w => cmd_fifo_din,
+ data_r => cmd_fifo_dout
+ );
+
+ -- DDR SDRAM command fsm
+ inst_sdram_cmd : entity work.sdram_cmd
+ Generic map
+ (
+ BL => BL
+ )
+ Port map
+ (
+ rst => ctrl_rst,
+ clk => sys_clk0_in,
+ u_tag_in => tag_fifo_out,
+ u_tag_out => u_tag,
+ phy_ctrl => phy_ctrl,
+ enable => cke,
+ cmd => sd_cmd,
+ cmd_we => sd_cmd_we,
+ cmd_ack => cmd_fifo_re,
+ sdr_cmd_ctrl => cmd_ctrl,
+ col_addr => col_fifo_out,
+ mode_word => mode_fifo_out,
+ sdr_ba => ba,
+ sdr_addr => addr
+ );
+
+ -- DDR phy
+ inst_ddr_phy : entity work.ddr_phy
+ Port map
+ (
+ sys_rst => ctrl_rst,
+ sys_clk0 => sys_clk0_in,
+ sys_clk270 => sys_clk270_in,
+ u_tag_in => u_tag,
+ u_tag_rd => u_tag_rd,
+ u_tag_wr => u_tag_wr,
+ read_clk => capture_clk270_in,
+ phy_ctrl => phy_ctrl,
+ part_ctrl => part_ctrl,
+ sdr_data_req_w => u_data_req_w,
+ sdr_data_req_r => u_data_req_r,
+ sdr_data_w => u_data_wr,
+ sdr_dm_wr_in => u_dm_wr_in,
+ sdr_dm_rd_in => u_dm_rd_in,
+ sdr_dm_rd_out => u_dm_rd_out,
+ sdr_data_r => u_data_rd,
+ sdr_data_vld => u_data_vld,
+ part_clk_p => sd_clk_p,
+ part_clk_n => sd_clk_n,
+ part_addr => sd_addr,
+ part_ba => sd_ba,
+ part_dm => sd_dm,
+ part_dqs => sd_dqs,
+ part_data => sd_data,
+ part_cs_n => sd_cs_n,
+ part_we_n => sd_we_n,
+ part_cas_n => sd_cas_n,
+ part_ras_n => sd_ras_n,
+ part_cke => sd_cke
+ );
+
+end architecture rtl;
+
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdram_types.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_types.vhd
new file mode 100644
index 0000000..d235d75
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_types.vhd
@@ -0,0 +1,133 @@
+-------------------------------------------------------------------------
+-- Project: SDRAM controller
+-- This file: Type definitions
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+
+use work.sdram_config.all;
+
+package sdram_types is
+
+ -----------------------------------------------------------------------------------------
+ -- Table of Timing Parameters as a function of operation
+
+ -- Derived constants from sdram_config
+
+ constant DDR_DQS_WIDTH : positive := DDR_DATA_WIDTH / 8; -- Number of data strobe lines
+ constant DDR_DM_WIDTH : positive := DDR_DATA_WIDTH / 8; -- Number of Data Mask Lines
+ constant SDR_DATA_WIDTH : positive := 2*DDR_DATA_WIDTH; --
+ constant SDR_DM_WIDTH : positive := 2*DDR_DM_WIDTH; --
+
+ subtype user_cmd_t is unsigned(1 downto 0);
+ constant UCMD_NOP : user_cmd_t := "00";
+ constant UCMD_READ : user_cmd_t := "01";
+ constant UCMD_WRITE : user_cmd_t := "10";
+ constant UCMD_LMR : user_cmd_t := "11";
+
+ subtype sdr_cmd_t is natural range 0 to 9;
+ constant SD_DESELECT : sdr_cmd_t := 0;
+ constant SD_NOP : sdr_cmd_t := 1;
+ constant SD_LMR : sdr_cmd_t := 2;
+ constant SD_ACT : sdr_cmd_t := 3;
+ constant SD_READ : sdr_cmd_t := 4;
+ constant SD_WRITE : sdr_cmd_t := 5;
+ constant SD_PRE : sdr_cmd_t := 6;
+ constant SD_BST : sdr_cmd_t := 7;
+ constant SD_AR : sdr_cmd_t := 8;
+ constant SD_SR : sdr_cmd_t := 9;
+
+ type sdr_state_t is (PWR_DOWN, PRECHARGE, MODE, IDLE, ROW_ACT, WRITE, WRITE_A, READ, READ_A, BURST_STOP, SELF_REF, AUTO_REF, PRE_PWR_DOWN, ACT_PWR_DOWN);
+ subtype user_addr_t is unsigned(DDR_BANK_WIDTH+DDR_ROW_ADDR_WIDTH+DDR_COL_ADDR_WIDTH-1 downto 0);
+ subtype sdr_addr_t is unsigned(DDR_ADDR_WIDTH-1 downto 0);
+ subtype sdr_ba_t is unsigned(DDR_BANK_WIDTH-1 downto 0);
+ subtype mode_word_t is unsigned(DDR_ADDR_WIDTH+DDR_BANK_WIDTH-1 downto 0);
+
+ subtype bank_addr_t is unsigned(DDR_BANK_WIDTH-1 downto 0);
+ subtype row_addr_t is unsigned(DDR_ADDR_WIDTH-1 downto 0);
+ subtype col_addr_t is unsigned(8 downto 0);
+
+ subtype cycle_cnt_t is natural range 0 to 10;
+
+ type phy_ctrl_t is
+ record
+ drive_en : std_logic;
+ re : std_logic;
+ we : std_logic;
+ utag_we : std_logic;
+ end record phy_ctrl_t;
+
+ type sdr_cmd_lines_t is
+ record
+ cs_n : std_logic;
+ ras_n : std_logic;
+ cas_n : std_logic;
+ we_n : std_logic;
+ end record sdr_cmd_lines_t;
+
+ type part_ctrl_t is
+ record
+ cmd : sdr_cmd_lines_t;
+ ba : unsigned(DDR_BANK_WIDTH-1 downto 0);
+ addr : unsigned(DDR_ADDR_WIDTH-1 downto 0);
+ cke : std_logic;
+ end record part_ctrl_t;
+
+ type part_cmd_array_t is array (sdr_cmd_t) of sdr_cmd_lines_t;
+ constant COMMAND : part_cmd_array_t :=
+ -- command cs_n ras_qn cas_qn we_qn
+ ( SD_DESELECT => ( '1', '1', '1', '1'),
+ SD_NOP => ( '0', '1', '1', '1'),
+ SD_LMR => ( '0', '0', '0', '0'),
+ SD_ACT => ( '0', '0', '1', '1'),
+ SD_READ => ( '0', '1', '0', '1'),
+ SD_WRITE => ( '0', '1', '0', '0'),
+ SD_PRE => ( '0', '0', '1', '0'),
+ SD_BST => ( '0', '1', '1', '0'),
+ SD_AR => ( '0', '0', '0', '1'),
+ SD_SR => ( '0', '0', '0', '1')
+ );
+
+ type part_timing_array_t is array (sdr_cmd_t) of cycle_cnt_t;
+ constant TIMING : part_timing_array_t :=
+ -- command cycle_cnt
+ ( SD_DESELECT => ( 0 ),
+ SD_NOP => ( 0 ),
+ SD_LMR => ( TMRD-1 ),
+ SD_ACT => ( TRCD-1 ),
+ SD_READ => ( TCAS-1 ),
+ SD_WRITE => ( TWR-1 ),
+ SD_PRE => ( TRP-1 ),
+ SD_BST => ( 0 ),
+ SD_AR => ( TRFC-1 ),
+ SD_SR => ( TRFC-1 )
+ );
+
+ type init_seq_t is
+ record
+ cmd : sdr_cmd_t;
+ mode_word : mode_word_t;
+ wait_cycle : natural;
+ end record init_seq_t;
+
+end sdram_types;
diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd
new file mode 100644
index 0000000..b55ced0
--- /dev/null
+++ b/lib/SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd
@@ -0,0 +1,495 @@
+-------------------------------------------------------------------------
+-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
+-- This file: cpu_embedded using cpu_core and rom
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- 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 3 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, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+use work.fifo_ctrl_pkg.all;
+use work.sdram_config.all;
+use work.sdram_types.all;
+
+entity tb_sdram_ctrl_frontend_wb is
+end;
+
+architecture struct of tb_sdram_ctrl_frontend_wb is
+
+ -- Number of user data words for simulation
+ constant CLK_PERIOD : time := 10 ns;
+ constant BURST_LEN : natural := 2;
+
+ signal rst : std_logic := '1';
+ signal clk : std_logic := '1';
+ signal locked : std_logic;
+ signal error : std_logic;
+ signal clk_out : std_logic;
+ signal clk_fb : std_logic;
+ signal part_clk_p : std_logic;
+ signal part_clk_n : std_logic;
+ signal part_cke : std_logic;
+ signal part_cs_n : std_logic;
+ signal part_we_n : std_logic;
+ signal part_ras_n : std_logic;
+ signal part_cas_n : std_logic;
+ signal part_ba : unsigned(DDR_BANK_WIDTH-1 downto 0) := (others => '0');
+ signal part_dm : unsigned(DDR_DM_WIDTH-1 downto 0) := (others => '0');
+ signal part_dqs : unsigned(DDR_DQS_WIDTH-1 downto 0) := (others => '0');
+ signal part_addr : unsigned(DDR_ADDR_WIDTH-1 downto 0) := (others => '0');
+ signal part_data : unsigned(DDR_DATA_WIDTH-1 downto 0) := (others => '0');
+
+ signal CLK_O : std_logic;
+ signal CLK270_O : std_logic;
+ signal CLK270VAR_O : std_logic;
+ signal RST_O : std_logic;
+ signal CYC_O : std_logic := '0';
+ signal STB_O : std_logic := '0';
+ signal WE_O : std_logic := '0';
+ signal SEL_O : unsigned(3 downto 0) := (others => '1');
+ signal ACK_I : std_logic;
+ signal RDY_I : std_logic;
+ signal ADDR_O : unsigned(31 downto 0) := (others => '-');
+ signal DAT_I : unsigned(31 downto 0);
+ signal DAT_O : unsigned(31 downto 0) := (others => '-');
+ signal dout_rst : std_logic := '0';
+ signal dout_reg : unsigned(31 downto 0);
+ signal dout_cnt : natural range 0 to 255;
+
+begin
+
+inst_clockgen : entity work.clockgen
+ GENERIC MAP
+ (
+ sys1_phaseshift => 0,
+ frequency_hz => 100E6
+ )
+ PORT MAP
+ (
+ -- Clocks and Reset
+ rst => rst, -- external async reset, low active
+ clk_in => clk, -- system clock (e.g. 100MHz), from board
+ clk_fb_in => clk_fb, -- feedback clock
+ sys1_clk0_out => open, -- System clock #1 (e.g. clock for DDR-SDRAM data capture), dcm#1 output 0°
+ sys1_clk270_out => CLK270VAR_O, -- System clock #1 (e.g. clock for DDR-SDRAM data capture), dcm#1 output 270°
+ sys0_clk0_out => CLK_O, -- System clock #0, dcm#0 output 0°
+ sys0_clk270_out => CLK270_O, -- System clock #0, dcm#0 output 270°
+ locked_out => locked, -- DCM locked status
+ error_out => error
+ );
+
+
+ clk_fb <= part_clk_p after 1 ns;
+ RST_O <= not locked;
+
+ -- DDR SDRAM Controller Core
+ sdram_ctrl_frontend_wb : entity work.sdram_ctrl_frontend_wb
+ GENERIC MAP
+ (
+ BL => BURST_LEN,
+ f_sysclk => 100E6,
+ fifo_depth => 2
+ )
+ PORT MAP
+ (
+ RST_I => RST_O,
+ CLK_I => CLK_O,
+ CLK270_I => CLK270_O,
+ CLK270VAR_I => CLK270VAR_O,
+
+ CYC_I => CYC_O,
+ STB_I => STB_O,
+ SEL_I => SEL_O,
+ WE_I => WE_O,
+ ACK_O => ACK_I,
+ RDY_O => RDY_I,
+ ADDR_I => ADDR_O,
+ DAT_I => DAT_O,
+ DAT_O => DAT_I,
+
+ -- SDRAM signals
+ sd_clk_p => part_clk_p,
+ sd_clk_n => part_clk_n,
+ sd_cke => part_cke,
+ sd_cs_n => part_cs_n,
+ sd_cas_n => part_cas_n,
+ sd_ras_n => part_ras_n,
+ sd_we_n => part_we_n,
+ sd_addr => part_addr,
+ sd_ba => part_ba,
+ sd_dm => part_dm,
+ sd_dqs => part_dqs,
+ sd_data => part_data
+
+ );
+
+
+ -- MICRON DDR SDRAM Simulation Model
+i_mt46v16m16_0 : entity work.mt46v16m16
+ port map
+ (
+ dq => std_logic_vector(part_data),
+ dqs => std_logic_vector(part_dqs),
+ addr => std_logic_vector(part_addr),
+ ba => std_logic_vector(part_ba),
+ clk => part_clk_p,
+ clk_n => part_clk_n,
+ cke => part_cke,
+ cs_n => part_cs_n,
+ ras_n => part_ras_n,
+ cas_n => part_cas_n,
+ we_n => part_we_n,
+ dm => std_logic_vector(part_dm)
+ );
+
+CLK_GEN: process
+ begin
+ wait for CLK_PERIOD/2;
+ clk <= not clk;
+ end process;
+
+read_register:
+ process(CLK_O)
+ begin
+ if rising_edge(CLK_O) then
+ if dout_rst = '1' then
+ dout_cnt <= 0;
+ elsif ACK_I = '1' and WE_O = '0' then
+ dout_reg <= DAT_I;
+ dout_cnt <= dout_cnt + 1;
+ end if;
+ end if;
+ end process;
+
+------------------------------------------------------------------------------------------
+
+STIMULUS: process
+
+ begin
+
+ wait for 3*CLK_PERIOD;
+ rst <= '0';
+
+ wait until RST_O = '0';
+ -- 8 single cycles
+ CYC_O <= '1';
+ STB_O <= '1';
+ WE_O <= '1';
+ DAT_O <= X"1234_0000";
+ ADDR_O <= X"0000_0000";
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ DAT_O <= DAT_O + 1;
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ STB_O <= '0';
+ CYC_O <= '0';
+
+
+ -- 8-word burst cycle
+ wait for 3*CLK_PERIOD;
+ dout_rst <= '1';
+ wait until rising_edge(CLK_O);
+ dout_rst <= '0';
+ CYC_O <= '1';
+ STB_O <= '1';
+ WE_O <= '0';
+ ADDR_O <= X"0000_0000";
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ STB_O <= '0';
+
+ wait until rising_edge(CLK_O) and dout_cnt = 7;
+ CYC_O <= '0';
+
+ wait for 3*CLK_PERIOD;
+ wait until rising_edge(CLK_O);
+ -- 1-word burst cycle
+ CYC_O <= '1';
+ STB_O <= '1';
+ WE_O <= '1';
+ SEL_O <= "0011";
+ ADDR_O <= X"0000_0080";
+ DAT_O <= X"DEADBEEF";
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ STB_O <= '0';
+ CYC_O <= '0';
+
+ wait for 3*CLK_PERIOD;
+ wait until rising_edge(CLK_O);
+ -- 1-word burst cycle
+ CYC_O <= '1';
+ STB_O <= '1';
+ WE_O <= '0';
+ ADDR_O <= X"0000_0080";
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ STB_O <= '0';
+ wait until rising_edge(CLK_O) and ACK_I = '1';
+ CYC_O <= '0';
+
+ -- 8-word burst cycle
+ wait for 3*CLK_PERIOD;
+ dout_rst <= '1';
+ wait until rising_edge(CLK_O);
+ dout_rst <= '0';
+ CYC_O <= '1';
+ STB_O <= '1';
+ WE_O <= '0';
+ ADDR_O <= X"0000_0000";
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ ADDR_O <= ADDR_O + 4;
+ wait until rising_edge(CLK_O) and RDY_I = '1';
+ STB_O <= '0';
+
+ wait until rising_edge(CLK_O) and dout_cnt = 54;
+ CYC_O <= '0';
+
+ wait;
+
+ end process;
+
+end architecture struct;