diff --git a/lib/SDRAM/ddr_sdr_v1_5/sim/tb_ctrl_sdr_wb32.fdo b/lib/SDRAM/ddr_sdr_v1_5/sim/tb_ctrl_sdr_wb32.fdo new file mode 100644 index 0000000..12a0f5f --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/sim/tb_ctrl_sdr_wb32.fdo @@ -0,0 +1,32 @@ +## NOTE: Do not edit this file. +## +if {[file exists work]} {vdel -lib work -all} + +vlib work +vcom -explicit -93 "../../../FIFO/src/fifo_ctrl_pkg.vhd" +vcom -explicit -93 "../../../rams/dpram_1w1r2c_ra_sim.vhd" +vcom -explicit -93 "../../../FIFO/src/gray_counter.vhd" +vcom -explicit -93 "../../../FIFO/src/fifo_async_ctrl.vhd" +vcom -explicit -93 "../../../FIFO/src/fifo_async.vhd" +vcom -explicit -93 "../../../FIFO/src/fifo_sync_ctrl.vhd" +vcom -explicit -93 "../../../FIFO/src/fifo_sync.vhd" +vcom -explicit -93 "../../../misc/utils_pkg.vhd" +vcom -explicit -93 "../src/sdram_config_mt48lc16m16.vhd" +vcom -explicit -93 "../src/sdram_types.vhd" +vcom -explicit -93 "../src/sdram_cmd.vhd" +vcom -explicit -93 "../src/sdram_ctrl.vhd" +vcom -explicit -93 "../src/ddr_clk_virtex4.vhd" +vcom -explicit -93 "../src/sdr_phy_virtex4.vhd" +vcom -explicit -93 "../src/sdram_ctrl_top.vhd" +vcom -explicit -93 "../src/sdram_ctrl_frontend_wb16.vhd" +vcom -explicit -93 "../src/ctrl_sdr_wb32.vhd" +vcom -explicit -93 "../src/mti_pkg.vhd" +vcom -explicit -93 "../src/mt48lc16m16a2.vhd" +vcom -explicit -93 "../src/tb_ctrl_sdr_wb32.vhd" + +vsim -t 1ps -lib work tb_ctrl_sdr_wb32 +do {tb_ctrl_sdr_wb32.wdo} +view wave +view structure +view signals +run 200us diff --git a/lib/SDRAM/ddr_sdr_v1_5/sim/tb_ctrl_sdr_wb32.wdo b/lib/SDRAM/ddr_sdr_v1_5/sim/tb_ctrl_sdr_wb32.wdo new file mode 100644 index 0000000..db538db --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/sim/tb_ctrl_sdr_wb32.wdo @@ -0,0 +1,82 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -divider J-Bus +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/clk_o +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/rst_o +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/cyc_o +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/stb_o +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/we_o +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/sel_o +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/ack_i +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/mrdy_o +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/srdy_i +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/addr_o +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/dat_i +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/dat_o +add wave -noupdate -divider SDRAM +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/sdclk +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/sdclk_fb +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/part_clk +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/part_cke +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/part_cs_n +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/part_we_n +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/part_ras_n +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/part_cas_n +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/part_ba +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/part_dqm +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/part_addr +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/part_data +add wave -noupdate -divider PHY +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/f_sdrclk +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/rst +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/clk +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/clk_fb +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/clk0_out +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/rst0_out +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/phy_in +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/phy_out +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/phy_ctrl +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_clk +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_dqm +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_data +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_ba +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_addr +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_cs_n +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_we_n +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_cas_n +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_ras_n +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_cke +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/drive +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/data_reg_r +add wave -noupdate -format Literal -expand /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/part_ctrl_reg +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/we_reg +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/read_en +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/clk0 +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/clk0_s +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/rst0 +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/clk_rd +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/clk_wr +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/locked +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/error +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/uut/inst_sdram_phy/u_tag_pipe +add wave -noupdate -divider Test +add wave -noupdate -format Logic /tb_ctrl_sdr_wb32/dout_rst +add wave -noupdate -format Literal -radix hexadecimal /tb_ctrl_sdr_wb32/dout_reg +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/dout_cnt +add wave -noupdate -format Literal /tb_ctrl_sdr_wb32/sd_cmd +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {3554765 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 {0 ps} {210 us} diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/ctrl_sdr_wb32.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/ctrl_sdr_wb32.vhd new file mode 100644 index 0000000..3083829 --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/src/ctrl_sdr_wb32.vhd @@ -0,0 +1,150 @@ +------------------------------------------------------------------------- +-- 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 ctrl_sdr_wb32 is + Generic + ( + BURST_LEN : natural := 2; + F_SYSCLK : real := 100.0; + F_SDRCLK : real := 100.0; + FIFO_DEPTH : integer := 4 + ); + Port + ( + RST_I : in STD_LOGIC; + CLK_I : in STD_LOGIC; + SDRAM_CLK_I : in STD_LOGIC; + SDRAM_CLK_FB_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; + MRDY_I : in STD_LOGIC; + SRDY_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 : 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_dqm : out unsigned(PART_DM_WIDTH-1 downto 0); + sd_data : inout unsigned(PART_DATA_WIDTH-1 downto 0) + + ); +end ctrl_sdr_wb32; + +architecture struct of ctrl_sdr_wb32 is + + signal sdram_clk0 : std_logic; + signal sdram_rst0 : std_logic; + + signal phy_ctrl : phy_ctrl_t; + signal phy_in : phy_in_t; + signal phy_out : phy_out_t; +begin + + -- DDR SDRAM Controller Core + sdram_ctrl_frontend_wb16 : entity work.sdram_ctrl_frontend_wb16 + GENERIC MAP + ( + BURST_LEN => BURST_LEN, + F_SYSCLK => F_SYSCLK, + F_SDRCLK => F_SDRCLK, + FIFO_DEPTH => FIFO_DEPTH + ) + PORT MAP + ( + RST_I => RST_I, + CLK_I => CLK_I, + SDRAM_RST0 => sdram_rst0, + SDRAM_CLK0 => sdram_clk0, + + CYC_I => CYC_I, + STB_I => STB_I, + SEL_I => SEL_I, + WE_I => WE_I, + ACK_O => ACK_O, + SRDY_O => SRDY_O, + MRDY_I => MRDY_I, + ADDR_I => ADDR_I, + DAT_I => DAT_I, + DAT_O => DAT_O, + + -- PHY signals + phy_in => phy_in, + phy_out => phy_out, + phy_ctrl => phy_ctrl + + ); + + -- DDR phy + inst_sdram_phy : entity work.sdram_phy + Generic map + ( + F_SDRCLK => F_SDRCLK + ) + Port map + ( + -- Clock interface + rst => RST_I, + clk => SDRAM_CLK_I, + clk_fb => SDRAM_CLK_FB_I, + clk0_out => sdram_clk0, + rst0_out => sdram_rst0, + + -- PHY interface + phy_in => phy_in, + phy_out => phy_out, + phy_ctrl => phy_ctrl, + + -- SDRAM part interface + part_clk => sd_clk, + part_addr => sd_addr, + part_ba => sd_ba, + part_dqm => sd_dqm, + 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 struct; diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/mt48lc16m16a2.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/mt48lc16m16a2.vhd new file mode 100644 index 0000000..fac375d --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/src/mt48lc16m16a2.vhd @@ -0,0 +1,1319 @@ +----------------------------------------------------------------------------------------- +-- +-- File Name: MT48LC16M16A2.VHD +-- Version: 0.0g +-- Date: June 29th, 2000 +-- Model: Behavioral +-- Simulator: Model Technology (PC version 5.3 PE) +-- +-- Dependencies: None +-- +-- Author: Son P. Huynh +-- Email: sphuynh@micron.com +-- Phone: (208) 368-3825 +-- Company: Micron Technology, Inc. +-- Part Number: MT48LC16M16A2 (4Mb x 16 x 4 Banks) +-- +-- Description: Micron 256Mb SDRAM +-- +-- Limitation: - Doesn't check for 4096-cycle refresh +-- +-- Note: - Set simulator resolution to "ps" accuracy +-- +-- 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 Phone Date Changes +-- ---- ---------------------------- ---------- ------------------------------------- +-- 0.0g Son Huynh 208-368-3825 06/29/2000 Add Load/Dump memory array +-- Micron Technology Inc. Modify tWR + tRAS timing check +-- +-- 0.0f Son Huynh 208-368-3825 07/08/1999 Fix tWR = 1 Clk + 7.5 ns (Auto) +-- Micron Technology Inc. Fix tWR = 15 ns (Manual) +-- Fix tRP (Autoprecharge to AutoRefresh) +-- +-- 0.0c Son P. Huynh 208-368-3825 04/08/1999 Fix tWR + tRP in Write with AP +-- Micron Technology Inc. Fix tRC check in Load Mode Register +-- +-- 0.0b Son P. Huynh 208-368-3825 01/06/1998 Derive from 64Mb SDRAM model +-- Micron Technology Inc. +-- +----------------------------------------------------------------------------------------- + +LIBRARY STD; + USE STD.TEXTIO.ALL; +LIBRARY IEEE; + USE IEEE.STD_LOGIC_1164.ALL; + USE IEEE.STD_LOGIC_ARITH.ALL; +LIBRARY WORK; + USE WORK.MTI_PKG.ALL; + +ENTITY mt48lc16m16a2 IS + GENERIC ( + -- Timing Parameters for -75 (PC133) and CAS Latency = 2 + tAC : TIME := 6.0 ns; + tHZ : TIME := 7.0 ns; + tOH : TIME := 2.7 ns; + tMRD : INTEGER := 2; -- 2 Clk Cycles + tRAS : TIME := 44.0 ns; + tRC : TIME := 66.0 ns; + tRCD : TIME := 20.0 ns; + tRP : TIME := 20.0 ns; + tRRD : TIME := 15.0 ns; + tWRa : TIME := 7.5 ns; -- A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) + tWRp : TIME := 15.0 ns; -- A2 Version - Precharge mode only (15 ns) + + tAH : TIME := 0.8 ns; + tAS : TIME := 1.5 ns; + tCH : TIME := 2.5 ns; + tCL : TIME := 2.5 ns; + tCK : TIME := 10.0 ns; + tDH : TIME := 0.8 ns; + tDS : TIME := 1.5 ns; + tCKH : TIME := 0.8 ns; + tCKS : TIME := 1.5 ns; + tCMH : TIME := 0.8 ns; + tCMS : TIME := 1.5 ns; + + addr_bits : INTEGER := 13; + data_bits : INTEGER := 16; + col_bits : INTEGER := 9 + ); + PORT ( + Dq : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z'); + Addr : IN STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + Ba : IN STD_LOGIC_VECTOR := "00"; + Clk : IN STD_LOGIC := '0'; + Cke : IN STD_LOGIC := '1'; + Cs_n : IN STD_LOGIC := '1'; + Ras_n : IN STD_LOGIC := '1'; + Cas_n : IN STD_LOGIC := '1'; + We_n : IN STD_LOGIC := '1'; + Dqm : IN STD_LOGIC_VECTOR (1 DOWNTO 0) := "00"; + Load : IN STD_LOGIC := '0'; -- FOR LOADING MEMORY ARRAY + Dump : IN STD_LOGIC := '0' -- FOR DUMPING MEMORY ARRAY + ); +END mt48lc16m16a2; + +ARCHITECTURE behave OF mt48lc16m16a2 IS + TYPE State IS (ACT, A_REF, BST, LMR, NOP, PRECH, READ, READ_A, WRITE, WRITE_A, LOAD_FILE, DUMP_FILE); + TYPE Array4xI IS ARRAY (3 DOWNTO 0) OF INTEGER; + TYPE Array4xT IS ARRAY (3 DOWNTO 0) OF TIME; + TYPE Array4xB IS ARRAY (3 DOWNTO 0) OF BIT; + TYPE Array4x2BV IS ARRAY (3 DOWNTO 0) OF BIT_VECTOR (1 DOWNTO 0); + TYPE Array4xCBV IS ARRAY (4 DOWNTO 0) OF BIT_VECTOR (Col_bits - 1 DOWNTO 0); + TYPE Array_state IS ARRAY (4 DOWNTO 0) OF State; + SIGNAL Operation : State := NOP; + SIGNAL Mode_reg : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Active_enable, Aref_enable, Burst_term : BIT := '0'; + SIGNAL Mode_reg_enable, Prech_enable, Read_enable, Write_enable : BIT := '0'; + SIGNAL Burst_length_1, Burst_length_2, Burst_length_4, Burst_length_8 : BIT := '0'; + SIGNAL Cas_latency_2, Cas_latency_3 : BIT := '0'; + SIGNAL Ras_in, Cas_in, We_in : BIT := '0'; + SIGNAL Write_burst_mode : BIT := '0'; + SIGNAL RAS_clk, Sys_clk, CkeZ : BIT := '0'; + + -- Checking internal wires + SIGNAL Pre_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Act_chk : BIT_VECTOR (3 DOWNTO 0) := "0000"; + SIGNAL Dq_in_chk, Dq_out_chk : BIT := '0'; + SIGNAL Bank_chk : BIT_VECTOR (1 DOWNTO 0) := "00"; + SIGNAL Row_chk : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL Col_chk : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + +BEGIN + -- CS# Decode + WITH Cs_n SELECT + Cas_in <= TO_BIT (Cas_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + Ras_in <= TO_BIT (Ras_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + WITH Cs_n SELECT + We_in <= TO_BIT (We_n, '1') WHEN '0', + '1' WHEN '1', + '1' WHEN OTHERS; + + -- Commands Decode + Active_enable <= NOT(Ras_in) AND Cas_in AND We_in; + Aref_enable <= NOT(Ras_in) AND NOT(Cas_in) AND We_in; + Burst_term <= Ras_in AND Cas_in AND NOT(We_in); + Mode_reg_enable <= NOT(Ras_in) AND NOT(Cas_in) AND NOT(We_in); + Prech_enable <= NOT(Ras_in) AND Cas_in AND NOT(We_in); + Read_enable <= Ras_in AND NOT(Cas_in) AND We_in; + Write_enable <= Ras_in AND NOT(Cas_in) AND NOT(We_in); + + -- Burst Length Decode + Burst_length_1 <= NOT(Mode_reg(2)) AND NOT(Mode_reg(1)) AND NOT(Mode_reg(0)); + 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); + + -- CAS Latency Decode + Cas_latency_2 <= NOT(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); + + -- Write Burst Mode + Write_burst_mode <= Mode_reg(9); + + -- RAS Clock for checking tWR and tRP + PROCESS + variable Clk0, Clk1 : integer := 0; + begin + RAS_clk <= '1'; + wait for 0.5 ns; + RAS_clk <= '0'; + wait for 0.5 ns; + if Clk0 > 100 or Clk1 > 100 then + wait; + else + if Clk = '1' and Cke = '1' then + Clk0 := 0; + Clk1 := Clk1 + 1; + elsif Clk = '0' and Cke = '1' then + Clk0 := Clk0 + 1; + Clk1 := 0; + end if; + end if; + END PROCESS; + + -- System Clock + int_clk : PROCESS (Clk) + begin + IF Clk'LAST_VALUE = '0' AND Clk = '1' THEN + CkeZ <= TO_BIT(Cke, '1'); + END IF; + Sys_clk <= CkeZ AND TO_BIT(Clk, '0'); + END PROCESS; + + state_register : PROCESS + -- NOTE: The extra bits in RAM_TYPE is for checking memory access. A logic 1 means + -- the location is in use. This will be checked when doing memory DUMP. + TYPE ram_type IS ARRAY (2**col_bits - 1 DOWNTO 0) OF BIT_VECTOR (data_bits DOWNTO 0); + TYPE ram_pntr IS ACCESS ram_type; + TYPE ram_stor IS ARRAY (2**addr_bits - 1 DOWNTO 0) OF ram_pntr; + VARIABLE Bank0 : ram_stor; + VARIABLE Bank1 : ram_stor; + VARIABLE Bank2 : ram_stor; + VARIABLE Bank3 : ram_stor; + VARIABLE Row_index, Col_index : INTEGER := 0; + VARIABLE Dq_temp : BIT_VECTOR (data_bits DOWNTO 0) := (OTHERS => '0'); + + VARIABLE Col_addr : Array4xCBV; + VARIABLE Bank_addr : Array4x2BV; + VARIABLE Dqm_reg0, Dqm_reg1 : BIT_VECTOR (1 DOWNTO 0) := "00"; + + VARIABLE Bank, Previous_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col_brst : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Row : BIT_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Col : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + VARIABLE Burst_counter : INTEGER := 0; + + VARIABLE Command : Array_state; + VARIABLE Bank_precharge : Array4x2BV; + VARIABLE A10_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Auto_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Read_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE Write_precharge : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_read : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_write : Array4xB := ('0' & '0' & '0' & '0'); + VARIABLE RW_interrupt_bank : BIT_VECTOR (1 DOWNTO 0) := "00"; + VARIABLE Count_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE Count_precharge : Array4xI := (0 & 0 & 0 & 0); + + VARIABLE Data_in_enable, Data_out_enable : BIT := '0'; + VARIABLE Pc_b0, Pc_b1, Pc_b2, Pc_b3 : BIT := '0'; + VARIABLE Act_b0, Act_b1, Act_b2, Act_b3 : BIT := '0'; + + -- Timing Check + VARIABLE MRD_chk : INTEGER := 0; + VARIABLE WR_counter : Array4xI := (0 & 0 & 0 & 0); + VARIABLE WR_time : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE WR_chkp : Array4xT := (0 ns & 0 ns & 0 ns & 0 ns); + VARIABLE RC_chk, RRD_chk : TIME := 0 ns; + VARIABLE RAS_chk0, RAS_chk1, RAS_chk2, RAS_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; + + -- Load and Dumb variables + FILE file_load : TEXT IS IN "loaddata.txt"; -- Data load + FILE file_dump : TEXT IS OUT "dumpdata.txt"; -- Data dump + VARIABLE bank_load : BIT_VECTOR ( 1 DOWNTO 0); + VARIABLE rows_load : BIT_VECTOR (12 DOWNTO 0); + VARIABLE cols_load : BIT_VECTOR ( 8 DOWNTO 0); + VARIABLE data_load : BIT_VECTOR (15 DOWNTO 0); + VARIABLE i, j : INTEGER; + VARIABLE good_load : BOOLEAN; + VARIABLE l : LINE; + + -- Initialize empty rows + PROCEDURE Init_mem (Bank : BIT_VECTOR (1 DOWNTO 0); 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 ram_type; -- Open new row for access + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP -- Filled row with zeros + FOR j IN (data_bits) 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 ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits) 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 ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits) 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 ram_type; + FOR i IN (2**col_bits - 1) DOWNTO 0 LOOP + FOR j IN (data_bits) 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 Col_int : INTEGER := 0; + VARIABLE Col_vec, Col_temp : BIT_VECTOR (col_bits - 1 DOWNTO 0) := (OTHERS => '0'); + BEGIN + -- Advance Burst Counter + Burst_counter := Burst_counter + 1; + + -- Burst Type + IF Mode_reg (3) = '0' THEN + Col_int := TO_INTEGER(Col); + Col_int := Col_int + 1; + TO_BITVECTOR (Col_int, Col_temp); + ELSIF Mode_reg (3) = '1' THEN + TO_BITVECTOR (Burst_counter, Col_vec); + Col_temp (2) := Col_vec (2) XOR Col_brst (2); + Col_temp (1) := Col_vec (1) XOR Col_brst (1); + Col_temp (0) := Col_vec (0) XOR Col_brst (0); + END IF; + + -- Burst Length + IF Burst_length_2 = '1' THEN + Col (0) := Col_temp (0); + ELSIF Burst_length_4 = '1' THEN + Col (1 DOWNTO 0) := Col_temp (1 DOWNTO 0); + ELSIF Burst_length_8 = '1' THEN + Col (2 DOWNTO 0) := Col_temp (2 DOWNTO 0); + ELSE + Col := Col_temp; + END IF; + + -- Burst Read Single Write + IF Write_burst_mode = '1' AND Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Data counter + IF Burst_length_1 = '1' THEN + IF Burst_counter >= 1 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_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, RAS_clk; + IF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '0' THEN + -- Internal Command Pipeline + Command(0) := Command(1); + Command(1) := Command(2); + Command(2) := Command(3); + Command(3) := NOP; + + Col_addr(0) := Col_addr(1); + Col_addr(1) := Col_addr(2); + Col_addr(2) := Col_addr(3); + Col_addr(3) := (OTHERS => '0'); + + Bank_addr(0) := Bank_addr(1); + Bank_addr(1) := Bank_addr(2); + Bank_addr(2) := Bank_addr(3); + Bank_addr(3) := "00"; + + Bank_precharge(0) := Bank_precharge(1); + Bank_precharge(1) := Bank_precharge(2); + Bank_precharge(2) := Bank_precharge(3); + Bank_precharge(3) := "00"; + + A10_precharge(0) := A10_precharge(1); + A10_precharge(1) := A10_precharge(2); + A10_precharge(2) := A10_precharge(3); + A10_precharge(3) := '0'; + + -- Operation Decode (Optional for showing current command on posedge clock / debug feature) + IF Active_enable = '1' THEN + Operation <= ACT; + ELSIF Aref_enable = '1' THEN + Operation <= A_REF; + ELSIF Burst_term = '1' THEN + Operation <= BST; + ELSIF Mode_reg_enable = '1' THEN + Operation <= LMR; + ELSIF Prech_enable = '1' THEN + Operation <= PRECH; + ELSIF Read_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= READ; + ELSE + Operation <= READ_A; + END IF; + ELSIF Write_enable = '1' THEN + IF Addr(10) = '0' THEN + Operation <= WRITE; + ELSE + Operation <= WRITE_A; + END IF; + ELSE + Operation <= NOP; + END IF; + + -- Dqm pipeline for Read + Dqm_reg0 := Dqm_reg1; + Dqm_reg1 := TO_BITVECTOR(Dqm); + + -- Read or Write with Auto Precharge Counter + IF Auto_precharge (0) = '1' THEN + Count_precharge (0) := Count_precharge (0) + 1; + END IF; + IF Auto_precharge (1) = '1' THEN + Count_precharge (1) := Count_precharge (1) + 1; + END IF; + IF Auto_precharge (2) = '1' THEN + Count_precharge (2) := Count_precharge (2) + 1; + END IF; + IF Auto_precharge (3) = '1' THEN + Count_precharge (3) := Count_precharge (3) + 1; + END IF; + + -- Auto Precharge Timer for tWR + if (Burst_length_1 = '1' OR Write_burst_mode = '1') then + if (Count_precharge(0) = 1) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 1) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 1) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 1) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_2 = '1') then + if (Count_precharge(0) = 2) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 2) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 2) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 2) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_4 = '1') then + if (Count_precharge(0) = 4) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 4) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 4) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 4) then + Count_time(3) := NOW; + end if; + elsif (Burst_length_8 = '1') then + if (Count_precharge(0) = 8) then + Count_time(0) := NOW; + end if; + if (Count_precharge(1) = 8) then + Count_time(1) := NOW; + end if; + if (Count_precharge(2) = 8) then + Count_time(2) := NOW; + end if; + if (Count_precharge(3) = 8) then + Count_time(3) := NOW; + end if; + end if; + + -- tMRD Counter + MRD_chk := MRD_chk + 1; + + -- tWR Counter + WR_counter(0) := WR_counter(0) + 1; + WR_counter(1) := WR_counter(1) + 1; + WR_counter(2) := WR_counter(2) + 1; + WR_counter(3) := WR_counter(3) + 1; + + + -- Auto Refresh + IF Aref_enable = '1' THEN + -- Auto Refresh to Auto Refresh + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Auto Refresh" + SEVERITY WARNING; + -- Precharge to Auto Refresh + ASSERT (NOW - RP_chk0 >= tRP OR NOW - RP_chk1 >= tRP OR NOW - RP_chk2 >= tRP OR NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Auto Refresh" + SEVERITY WARNING; + -- All banks must be idle before refresh + IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All banks must be Precharge before Auto Refresh" + SEVERITY WARNING; + END IF; + -- Record current tRC time + RC_chk := NOW; + END IF; + + -- Load Mode Register + IF Mode_reg_enable = '1' THEN + Mode_reg <= TO_BITVECTOR (Addr); + IF (Pc_b3 ='0' OR Pc_b2 = '0' OR Pc_b1 ='0' OR Pc_b0 = '0') THEN + ASSERT (FALSE) + REPORT "All bank must be Precharge before Load Mode Register" + SEVERITY WARNING; + END IF; + -- REF to LMR + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Load Mode Register" + SEVERITY WARNING; + -- LMR to LMR + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Load Mode Register" + SEVERITY WARNING; + -- Record current tMRD time + MRD_chk := 0; + END IF; + + -- Active Block (latch Bank and Row Address) + IF Active_enable = '1' THEN + IF Ba = "00" AND Pc_b0 = '1' THEN + Act_b0 := '1'; + Pc_b0 := '0'; + B0_row_addr := TO_BITVECTOR (Addr); + RCD_chk0 := NOW; + RAS_chk0 := NOW; + -- Precharge to Active Bank 0 + ASSERT (NOW - RP_chk0 >= tRP) + REPORT "tRP violation during Activate Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '1' THEN + Act_b1 := '1'; + Pc_b1 := '0'; + B1_row_addr := TO_BITVECTOR (Addr); + RCD_chk1 := NOW; + RAS_chk1 := NOW; + -- Precharge to Active Bank 1 + ASSERT (NOW - RP_chk1 >= tRP) + REPORT "tRP violation during Activate Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '1' THEN + Act_b2 := '1'; + Pc_b2 := '0'; + B2_row_addr := TO_BITVECTOR (Addr); + RCD_chk2 := NOW; + RAS_chk2 := NOW; + -- Precharge to Active Bank 2 + ASSERT (NOW - RP_chk2 >= tRP) + REPORT "tRP violation during Activate Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '1' THEN + Act_b3 := '1'; + Pc_b3 := '0'; + B3_row_addr := TO_BITVECTOR (Addr); + RCD_chk3 := NOW; + RAS_chk3 := NOW; + -- Precharge to Active Bank 3 + ASSERT (NOW - RP_chk3 >= tRP) + REPORT "tRP violation during Activate Bank 3" + SEVERITY WARNING; + ELSIF Ba = "00" AND Pc_b0 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 0 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "01" AND Pc_b1 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 1 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "10" AND Pc_b2 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 2 is not Precharged" + SEVERITY WARNING; + ELSIF Ba = "11" AND Pc_b3 = '0' THEN + ASSERT (FALSE) + REPORT "Bank 3 is not Precharged" + SEVERITY WARNING; + END IF; + -- Active Bank A to Active Bank B + IF ((Previous_bank /= TO_BITVECTOR (Ba)) AND (NOW - RRD_chk < tRRD)) THEN + ASSERT (FALSE) + REPORT "tRRD violation during Activate" + SEVERITY WARNING; + END IF; + -- LMR to ACT + ASSERT (MRD_chk >= tMRD) + REPORT "tMRD violation during Activate" + SEVERITY WARNING; + -- AutoRefresh to Activate + ASSERT (NOW - RC_chk >= tRC) + REPORT "tRC violation during Activate" + SEVERITY WARNING; + -- Record variable for checking violation + RRD_chk := NOW; + Previous_bank := TO_BITVECTOR (Ba); + END IF; + + -- Precharge Block + IF Prech_enable = '1' THEN + IF Addr(10) = '1' THEN + Pc_b0 := '1'; + Pc_b1 := '1'; + Pc_b2 := '1'; + Pc_b3 := '1'; + Act_b0 := '0'; + Act_b1 := '0'; + Act_b2 := '0'; + Act_b3 := '0'; + RP_chk0 := NOW; + RP_chk1 := NOW; + RP_chk2 := NOW; + RP_chk3 := NOW; + -- Activate to Precharge all banks + ASSERT ((NOW - RAS_chk0 >= tRAS) OR (NOW - RAS_chk1 >= tRAS)) + REPORT "tRAS violation during Precharge all banks" + SEVERITY WARNING; + -- tWR violation check for Write + IF ((NOW - WR_chkp(0) < tWRp) OR (NOW - WR_chkp(1) < tWRp) OR + (NOW - WR_chkp(2) < tWRp) OR (NOW - WR_chkp(3) < tWRp)) THEN + ASSERT (FALSE) + REPORT "tWR violation during Precharge ALL banks" + SEVERITY WARNING; + END IF; + ELSIF Addr(10) = '0' THEN + IF Ba = "00" THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + -- Activate to Precharge bank 0 + ASSERT (NOW - RAS_chk0 >= tRAS) + REPORT "tRAS violation during Precharge bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + -- Activate to Precharge bank 1 + ASSERT (NOW - RAS_chk1 >= tRAS) + REPORT "tRAS violation during Precharge bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + -- Activate to Precharge bank 2 + ASSERT (NOW - RAS_chk2 >= tRAS) + REPORT "tRAS violation during Precharge bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + -- Activate to Precharge bank 3 + ASSERT (NOW - RAS_chk3 >= tRAS) + REPORT "tRAS violation during Precharge bank 3" + SEVERITY WARNING; + END IF; + -- tWR violation check for Write + ASSERT (NOW - WR_chkp(TO_INTEGER(Ba)) >= tWRp) + REPORT "tWR violation during Precharge" + SEVERITY WARNING; + END IF; + -- Terminate a Write Immediately (if same bank or all banks) + IF (Data_in_enable = '1' AND (Bank = TO_BITVECTOR(Ba) OR Addr(10) = '1')) THEN + Data_in_enable := '0'; + END IF; + -- Precharge Command Pipeline for READ + IF CAS_latency_3 = '1' THEN + Command(2) := PRECH; + Bank_precharge(2) := TO_BITVECTOR (Ba); + A10_precharge(2) := TO_BIT(Addr(10)); + ELSIF CAS_latency_2 = '1' THEN + Command(1) := PRECH; + Bank_precharge(1) := TO_BITVECTOR (Ba); + A10_precharge(1) := TO_BIT(Addr(10)); + END IF; + END IF; + + -- Burst Terminate + IF Burst_term = '1' THEN + -- Terminate a Write immediately + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + -- Terminate a Read depend on CAS Latency + IF CAS_latency_3 = '1' THEN + Command(2) := BST; + ELSIF CAS_latency_2 = '1' THEN + Command(1) := BST; + END IF; + END IF; + + -- Read, Write, Column Latch + IF Read_enable = '1' OR Write_enable = '1' THEN + -- Check to see if bank is open (ACT) for Read or Write + IF ((Ba="00" AND Pc_b0='1') OR (Ba="01" AND Pc_b1='1') OR (Ba="10" AND Pc_b2='1') OR (Ba="11" AND Pc_b3='1')) THEN + ASSERT (FALSE) + REPORT "Cannot Read or Write - Bank is not Activated" + SEVERITY WARNING; + END IF; + -- Activate to Read or Write + IF Ba = "00" THEN + ASSERT (NOW - RCD_chk0 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 0" + SEVERITY WARNING; + ELSIF Ba = "01" THEN + ASSERT (NOW - RCD_chk1 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 1" + SEVERITY WARNING; + ELSIF Ba = "10" THEN + ASSERT (NOW - RCD_chk2 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 2" + SEVERITY WARNING; + ELSIF Ba = "11" THEN + ASSERT (NOW - RCD_chk3 >= tRCD) + REPORT "tRCD violation during Read or Write to Bank 3" + SEVERITY WARNING; + END IF; + + -- Read Command + IF Read_enable = '1' THEN + -- CAS Latency Pipeline + IF Cas_latency_3 = '1' THEN + IF Addr(10) = '1' THEN + Command(2) := READ_A; + ELSE + Command(2) := READ; + END IF; + Col_addr (2) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (2) := TO_BITVECTOR (Ba); + ELSIF Cas_latency_2 = '1' THEN + IF Addr(10) = '1' THEN + Command(1) := READ_A; + ELSE + Command(1) := READ; + END IF; + Col_addr (1) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (1) := TO_BITVECTOR (Ba); + END IF; + + -- Read intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write Command + ELSIF Write_enable = '1' THEN + IF Addr(10) = '1' THEN + Command(0) := WRITE_A; + ELSE + Command(0) := WRITE; + END IF; + Col_addr (0) := TO_BITVECTOR (Addr(col_bits - 1 DOWNTO 0)); + Bank_addr (0) := TO_BITVECTOR (Ba); + + -- Write intterupt a Write (terminate Write immediately) + IF Data_in_enable = '1' THEN + Data_in_enable := '0'; + END IF; + + -- Write interrupt a Read (terminate Read immediately) + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + -- Interrupt a Write with Auto Precharge + IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Write_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN + RW_interrupt_write(TO_INTEGER(RW_Interrupt_Bank)) := '1'; + END IF; + + -- Interrupt a Read with Auto Precharge + IF Auto_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' AND Read_precharge(TO_INTEGER(RW_Interrupt_Bank)) = '1' THEN + RW_interrupt_read(TO_INTEGER(RW_Interrupt_Bank)) := '1'; + END IF; + + -- Read or Write with Auto Precharge + IF Addr(10) = '1' THEN + Auto_precharge (TO_INTEGER(Ba)) := '1'; + Count_precharge (TO_INTEGER(Ba)) := 0; + RW_Interrupt_Bank := TO_BitVector(Ba); + IF Read_enable = '1' THEN + Read_precharge (TO_INTEGER(Ba)) := '1'; + ELSIF Write_enable = '1' THEN + Write_precharge (TO_INTEGER(Ba)) := '1'; + END IF; + END IF; + END IF; + + -- Read with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. BL/2 cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Read_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(0) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8))) OR + (RW_interrupt_read(0) = '1')) THEN + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + Auto_precharge(0) := '0'; + Read_precharge(0) := '0'; + RW_interrupt_read(0) := '0'; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Read_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(1) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8))) OR + (RW_interrupt_read(1) = '1')) THEN + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + Auto_precharge(1) := '0'; + Read_precharge(1) := '0'; + RW_interrupt_read(1) := '0'; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Read_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(2) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8))) OR + (RW_interrupt_read(2) = '1')) THEN + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + Auto_precharge(2) := '0'; + Read_precharge(2) := '0'; + RW_interrupt_read(2) := '0'; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Read_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + ((Burst_length_1 = '1' AND Count_precharge(3) >= 1) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8))) OR + (RW_interrupt_read(3) = '1')) THEN + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + Auto_precharge(3) := '0'; + Read_precharge(3) := '0'; + RW_interrupt_read(3) := '0'; + END IF; + END IF; + + -- Internal Precharge or Bst + IF Command(0) = PRECH THEN -- PRECH terminate a read if same bank or all banks + IF Bank_precharge(0) = Bank OR A10_precharge(0) = '1' THEN + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + ELSIF Command(0) = BST THEN -- BST terminate a read regardless of bank + IF Data_out_enable = '1' THEN + Data_out_enable := '0'; + END IF; + END IF; + + IF Data_out_enable = '0' THEN + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tOH; + END IF; + + -- Detect Read or Write Command + IF Command(0) = READ OR Command(0) = READ_A THEN + Bank := Bank_addr (0); + Col := Col_addr (0); + Col_brst := Col_addr (0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '0'; + Data_out_enable := '1'; + ELSIF Command(0) = WRITE OR Command(0) = WRITE_A THEN + Bank := Bank_addr(0); + Col := Col_addr(0); + Col_brst := Col_addr(0); + IF Bank_addr (0) = "00" THEN + Row := B0_row_addr; + ELSIF Bank_addr (0) = "01" THEN + Row := B1_row_addr; + ELSIF Bank_addr (0) = "10" THEN + Row := B2_row_addr; + ELSE + Row := B3_row_addr; + END IF; + Burst_counter := 0; + Data_in_enable := '1'; + Data_out_enable := '0'; + END IF; + + -- DQ (Driver / Receiver) + Row_index := TO_INTEGER (Row); + Col_index := TO_INTEGER (Col); + IF Data_in_enable = '1' THEN + IF Dqm /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank0 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0)); + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank1 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0)); + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank2 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0)); + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + IF Dqm = "01" THEN + Dq_temp (15 DOWNTO 8) := TO_BITVECTOR (Dq (15 DOWNTO 8)); + ELSIF Dqm = "10" THEN + Dq_temp (7 DOWNTO 0) := TO_BITVECTOR (Dq (7 DOWNTO 0)); + ELSE + Dq_temp (15 DOWNTO 0) := TO_BITVECTOR (Dq (15 DOWNTO 0)); + END IF; + Bank3 (Row_index) (Col_index) := ('1' & Dq_temp(data_bits - 1 DOWNTO 0)); + END IF; + WR_chkp(TO_INTEGER(Bank)) := NOW; + WR_counter(TO_INTEGER(Bank)) := 0; + END IF; + Burst_decode; + ELSIF Data_out_enable = '1' THEN + IF Dqm_reg0 /= "11" THEN + Init_mem (Bank, Row_index); + IF Bank = "00" THEN + Dq_temp := Bank0 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "01" THEN + Dq_temp := Bank1 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "10" THEN + Dq_temp := Bank2 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + ELSIF Bank = "11" THEN + Dq_temp := Bank3 (Row_index) (Col_index); + IF Dqm_reg0 = "00" THEN + Dq (15 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 0)) AFTER tAC; + ELSIF Dqm_reg0 = "01" THEN + Dq (15 DOWNTO 8) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (15 DOWNTO 8)) AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + ELSIF Dqm_reg0 = "10" THEN + Dq (15 DOWNTO 8) <= TRANSPORT (OTHERS => 'Z') AFTER tAC; + Dq (7 DOWNTO 0) <= TRANSPORT TO_STDLOGICVECTOR (Dq_temp (7 DOWNTO 0)) AFTER tAC; + END IF; + END IF; + ELSE + Dq <= TRANSPORT (OTHERS => 'Z') AFTER tHZ; + END IF; + Burst_decode; + END IF; + ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '1' AND Dump = '0' THEN + Operation <= LOAD_FILE; + ASSERT (FALSE) REPORT "Reading memory array from file. This operation may take several minutes. Please wait..." + SEVERITY NOTE; + WHILE NOT endfile(file_load) LOOP + readline(file_load, l); + -- skip the line if it doesn't start with a number + read(l, bank_load, good => good_load); + NEXT WHEN NOT good_load; + read(l, rows_load); + read(l, cols_load); + read(l, data_load); + Init_Mem (Bank_Load, To_Integer(Rows_Load)); + IF Bank_Load = "00" THEN + Bank0 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)) := ('1' & Data_Load); + ELSIF Bank_Load = "01" THEN + Bank1 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)) := ('1' & Data_Load); + ELSIF Bank_Load = "10" THEN + Bank2 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)) := ('1' & Data_Load); + ELSIF Bank_Load = "11" THEN + Bank3 (To_Integer(Rows_Load)) (To_Integer(Cols_Load)) := ('1' & Data_Load); + END IF; + END LOOP; + ELSIF Sys_clk'event AND Sys_clk = '1' AND Load = '0' AND Dump = '1' THEN + Operation <= DUMP_FILE; + ASSERT (FALSE) REPORT "Writing memory array to file. This operation may take several minutes. Please wait..." + SEVERITY NOTE; + WRITE (l, string'("# Micron Technology, Inc. (FILE DUMP / MEMORY DUMP)")); + WRITELINE (file_dump, l); + WRITE (l, string'("# BA ROWS COLS DQ")); + WRITELINE (file_dump, l); + WRITE (l, string'("# -- ------------- --------- ----------------")); + WRITELINE (file_dump, l); + -- Dumping Bank 0 + FOR i IN 0 TO 2**addr_bits -1 LOOP + -- Check if ROW is NULL + IF Bank0 (i) /= NULL THEN + For j IN 0 TO 2**col_bits - 1 LOOP + -- Check if COL is NULL + NEXT WHEN Bank0 (i) (j) (data_bits) = '0'; + WRITE (l, string'("00"), right, 4); + WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1); + WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1); + WRITE (l, Bank0 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1); + WRITELINE (file_dump, l); + END LOOP; + END IF; + END LOOP; + -- Dumping Bank 1 + FOR i IN 0 TO 2**addr_bits -1 LOOP + -- Check if ROW is NULL + IF Bank1 (i) /= NULL THEN + For j IN 0 TO 2**col_bits - 1 LOOP + -- Check if COL is NULL + NEXT WHEN Bank1 (i) (j) (data_bits) = '0'; + WRITE (l, string'("01"), right, 4); + WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1); + WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1); + WRITE (l, Bank1 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1); + WRITELINE (file_dump, l); + END LOOP; + END IF; + END LOOP; + -- Dumping Bank 2 + FOR i IN 0 TO 2**addr_bits -1 LOOP + -- Check if ROW is NULL + IF Bank2 (i) /= NULL THEN + For j IN 0 TO 2**col_bits - 1 LOOP + -- Check if COL is NULL + NEXT WHEN Bank2 (i) (j) (data_bits) = '0'; + WRITE (l, string'("10"), right, 4); + WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1); + WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1); + WRITE (l, Bank2 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1); + WRITELINE (file_dump, l); + END LOOP; + END IF; + END LOOP; + -- Dumping Bank 3 + FOR i IN 0 TO 2**addr_bits -1 LOOP + -- Check if ROW is NULL + IF Bank3 (i) /= NULL THEN + For j IN 0 TO 2**col_bits - 1 LOOP + -- Check if COL is NULL + NEXT WHEN Bank3 (i) (j) (data_bits) = '0'; + WRITE (l, string'("11"), right, 4); + WRITE (l, To_BitVector(Conv_Std_Logic_Vector(i, addr_bits)), right, addr_bits+1); + WRITE (l, To_BitVector(Conv_std_Logic_Vector(j, col_bits)), right, col_bits+1); + WRITE (l, Bank3 (i) (j) (data_bits -1 DOWNTO 0), right, data_bits+1); + WRITELINE (file_dump, l); + END LOOP; + END IF; + END LOOP; + END IF; + + -- Write with AutoPrecharge Calculation + -- The device start internal precharge when: + -- 1. tWR cycles after command + -- and 2. Meet tRAS requirement + -- or 3. Interrupt by a Read or Write (with or without Auto Precharge) + IF ((Auto_precharge(0) = '1') AND (Write_precharge(0) = '1')) THEN + IF (((NOW - RAS_chk0 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(0) >= 1 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(0) >= 2 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(0) >= 4 AND NOW - Count_time(0) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(0) >= 8 AND NOW - Count_time(0) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(0) >= tWRa)) THEN + Auto_precharge(0) := '0'; + Write_precharge(0) := '0'; + RW_interrupt_write(0) := '0'; + Pc_b0 := '1'; + Act_b0 := '0'; + RP_chk0 := NOW; + ASSERT FALSE REPORT "Start Internal Precharge Bank 0" SEVERITY NOTE; + END IF; + END IF; + IF ((Auto_precharge(1) = '1') AND (Write_precharge(1) = '1')) THEN + IF (((NOW - RAS_chk1 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(1) >= 1 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(1) >= 2 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(1) >= 4 AND NOW - Count_time(1) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(1) >= 8 AND NOW - Count_time(1) >= tWRa))) OR + (RW_interrupt_write(1) = '1' AND WR_counter(1) >= 1 AND NOW - WR_time(1) >= tWRa)) THEN + Auto_precharge(1) := '0'; + Write_precharge(1) := '0'; + RW_interrupt_write(1) := '0'; + Pc_b1 := '1'; + Act_b1 := '0'; + RP_chk1 := NOW; + END IF; + END IF; + IF ((Auto_precharge(2) = '1') AND (Write_precharge(2) = '1')) THEN + IF (((NOW - RAS_chk2 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(2) >= 1 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(2) >= 2 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(2) >= 4 AND NOW - Count_time(2) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(2) >= 8 AND NOW - Count_time(2) >= tWRa))) OR + (RW_interrupt_write(2) = '1' AND WR_counter(2) >= 1 AND NOW - WR_time(2) >= tWRa)) THEN + Auto_precharge(2) := '0'; + Write_precharge(2) := '0'; + RW_interrupt_write(2) := '0'; + Pc_b2 := '1'; + Act_b2 := '0'; + RP_chk2 := NOW; + END IF; + END IF; + IF ((Auto_precharge(3) = '1') AND (Write_precharge(3) = '1')) THEN + IF (((NOW - RAS_chk3 >= tRAS) AND + (((Burst_length_1 = '1' OR Write_burst_mode = '1' ) AND Count_precharge(3) >= 1 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_2 = '1' AND Count_precharge(3) >= 2 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_4 = '1' AND Count_precharge(3) >= 4 AND NOW - Count_time(3) >= tWRa) OR + (Burst_length_8 = '1' AND Count_precharge(3) >= 8 AND NOW - Count_time(3) >= tWRa))) OR + (RW_interrupt_write(0) = '1' AND WR_counter(0) >= 1 AND NOW - WR_time(3) >= tWRa)) THEN + Auto_precharge(3) := '0'; + Write_precharge(3) := '0'; + RW_interrupt_write(3) := '0'; + Pc_b3 := '1'; + Act_b3 := '0'; + RP_chk3 := NOW; + END IF; + END IF; + + -- Checking internal wires (Optional for debug purpose) + Pre_chk (0) <= Pc_b0; + Pre_chk (1) <= Pc_b1; + Pre_chk (2) <= Pc_b2; + Pre_chk (3) <= Pc_b3; + Act_chk (0) <= Act_b0; + Act_chk (1) <= Act_b1; + Act_chk (2) <= Act_b2; + Act_chk (3) <= Act_b3; + Dq_in_chk <= Data_in_enable; + Dq_out_chk <= Data_out_enable; + Bank_chk <= Bank; + Row_chk <= Row; + Col_chk <= Col; + END PROCESS; + + + -- Clock timing checks + Clock_check : PROCESS + VARIABLE Clk_low, Clk_high : TIME := 0 ns; + BEGIN + WAIT ON Clk; + IF (Clk = '1' AND NOW >= 10 ns) THEN + ASSERT (NOW - Clk_low >= tCL) + REPORT "tCL violation" + SEVERITY WARNING; + ASSERT (NOW - Clk_high >= tCK) + REPORT "tCK violation" + SEVERITY WARNING; + Clk_high := NOW; + ELSIF (Clk = '0' AND NOW /= 0 ns) THEN + ASSERT (NOW - Clk_high >= tCH) + REPORT "tCH violation" + SEVERITY WARNING; + Clk_low := NOW; + END IF; + END PROCESS; + + -- Setup timing checks + Setup_check : PROCESS + BEGIN + WAIT ON Clk; + IF Clk = '1' THEN + ASSERT(Cke'LAST_EVENT >= tCKS) + REPORT "CKE Setup time violation -- tCKS" + SEVERITY WARNING; + ASSERT(Cs_n'LAST_EVENT >= tCMS) + REPORT "CS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT >= tCMS) + REPORT "CAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT >= tCMS) + REPORT "RAS# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT >= tCMS) + REPORT "WE# Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT >= tCMS) + REPORT "Dqm Setup time violation -- tCMS" + SEVERITY WARNING; + ASSERT(Addr'LAST_EVENT >= tAS) + REPORT "ADDR Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT >= tAS) + REPORT "BA Setup time violation -- tAS" + SEVERITY WARNING; + ASSERT(Dq'LAST_EVENT >= tDS) + REPORT "Dq Setup time violation -- tDS" + SEVERITY WARNING; + END IF; + END PROCESS; + + -- Hold timing checks + Hold_check : PROCESS + BEGIN + WAIT ON Clk'DELAYED (tCKH), Clk'DELAYED (tCMH), Clk'DELAYED (tAH), Clk'DELAYED (tDH); + IF Clk'DELAYED (tCKH) = '1' THEN + ASSERT(Cke'LAST_EVENT > tCKH) + REPORT "CKE Hold time violation -- tCKH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tCMH) = '1' THEN + ASSERT(Cs_n'LAST_EVENT > tCMH) + REPORT "CS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Cas_n'LAST_EVENT > tCMH) + REPORT "CAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Ras_n'LAST_EVENT > tCMH) + REPORT "RAS# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(We_n'LAST_EVENT > tCMH) + REPORT "WE# Hold time violation -- tCMH" + SEVERITY WARNING; + ASSERT(Dqm'LAST_EVENT > tCMH) + REPORT "Dqm Hold time violation -- tCMH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tAH) = '1' THEN + ASSERT(Addr'LAST_EVENT > tAH) + REPORT "ADDR Hold time violation -- tAH" + SEVERITY WARNING; + ASSERT(Ba'LAST_EVENT > tAH) + REPORT "BA Hold time violation -- tAH" + SEVERITY WARNING; + END IF; + IF Clk'DELAYED (tDH) = '1' THEN + ASSERT(Dq'LAST_EVENT > tDH) + REPORT "Dq Hold time violation -- tDH" + SEVERITY WARNING; + END IF; + END PROCESS; + +END behave; diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/mti_pkg.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/mti_pkg.vhd new file mode 100644 index 0000000..80a9639 --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/src/mti_pkg.vhd @@ -0,0 +1,139 @@ +--***************************************************************************** +-- +-- Micron Semiconductor Products, Inc. +-- +-- Copyright 1997, Micron Semiconductor Products, Inc. +-- All rights reserved. +-- +--***************************************************************************** + +LIBRARY ieee; + USE ieee.std_logic_1164.ALL; + +PACKAGE mti_pkg IS + + FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC; + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER; + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER; + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER; + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR); + +END mti_pkg; + +PACKAGE BODY mti_pkg IS + + -- Convert BIT to STD_LOGIC + FUNCTION To_StdLogic (s : BIT) RETURN STD_LOGIC IS + BEGIN + CASE s IS + WHEN '0' => RETURN ('0'); + WHEN '1' => RETURN ('1'); + WHEN OTHERS => RETURN ('0'); + END CASE; + END; + + -- Convert STD_LOGIC to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + IF input = '1' THEN + result := weight; + ELSE + result := 0; -- if unknowns, default to logic 0 + END IF; + RETURN result; + END TO_INTEGER; + + -- Convert BIT_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : BIT_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Convert STD_LOGIC_VECTOR to INTEGER + FUNCTION TO_INTEGER (input : STD_LOGIC_VECTOR) RETURN INTEGER IS + VARIABLE result : INTEGER := 0; + VARIABLE weight : INTEGER := 1; + BEGIN + FOR i IN input'LOW TO input'HIGH LOOP + IF input(i) = '1' THEN + result := result + weight; + ELSE + result := result + 0; -- if unknowns, default to logic 0 + END IF; + weight := weight * 2; + END LOOP; + RETURN result; + END TO_INTEGER; + + -- Conver INTEGER to BIT_VECTOR + PROCEDURE TO_BITVECTOR (VARIABLE input : IN INTEGER; VARIABLE output : OUT BIT_VECTOR) IS + VARIABLE work,offset,outputlen,j : INTEGER := 0; + BEGIN + --length of vector + IF output'LENGTH > 32 THEN + outputlen := 32; + offset := output'LENGTH - 32; + IF input >= 0 THEN + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '0'; + END LOOP; + ELSE + FOR i IN offset-1 DOWNTO 0 LOOP + output(output'HIGH - i) := '1'; + END LOOP; + END IF; + ELSE + outputlen := output'LENGTH; + END IF; + --positive value + IF (input >= 0) THEN + work := input; + j := outputlen - 1; + FOR i IN 1 to 32 LOOP + IF j >= 0 then + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '0'; + ELSE + output(output'HIGH-j-offset) := '1'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '0'; + END IF; + --negative value + ELSE + work := (-input) - 1; + j := outputlen - 1; + FOR i IN 1 TO 32 LOOP + IF j>= 0 THEN + IF (work MOD 2) = 0 THEN + output(output'HIGH-j-offset) := '1'; + ELSE + output(output'HIGH-j-offset) := '0'; + END IF; + END IF; + work := work / 2; + j := j - 1; + END LOOP; + IF outputlen = 32 THEN + output(output'HIGH) := '1'; + END IF; + END IF; + END TO_BITVECTOR; + +END mti_pkg; diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdr_phy_virtex4.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdr_phy_virtex4.vhd new file mode 100644 index 0000000..7d167f2 --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdr_phy_virtex4.vhd @@ -0,0 +1,266 @@ +------------------------------------------------------------------------- +-- 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 sdram_phy is + Generic + ( + F_SDRCLK : real := 100.0 + ); + Port + ( + rst : in STD_LOGIC; + clk : in STD_LOGIC; + clk_fb : in STD_LOGIC; + clk0_out : out STD_LOGIC; + rst0_out : out STD_LOGIC; + phy_in : in phy_in_t; + phy_out : out phy_out_t; + phy_ctrl : in phy_ctrl_t; + part_clk : out STD_LOGIC; + part_dqm : out unsigned(PART_DM_WIDTH-1 downto 0); + part_data : inout unsigned(PART_DATA_WIDTH-1 downto 0); + part_ba : out unsigned(PART_BANK_WIDTH-1 downto 0); + part_addr : out unsigned(PART_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 sdram_phy; + +architecture tech of sdram_phy is + + signal drive : std_logic; + signal data_reg_r : unsigned(BUS_DATA_WIDTH-1 downto 0); + signal part_ctrl_reg : part_ctrl_t; + signal we_reg : std_logic; + signal read_en : std_logic; + + signal clk0 : std_logic; + signal clk0_s : std_logic; + signal rst0 : std_logic; + signal clk_rd : std_logic; + signal clk_wr : std_logic; + + signal locked : std_logic; + signal error : 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; + + attribute KEEP : string; + attribute KEEP of clk0 : signal is "TRUE"; + +begin + + clk0_out <= clk0_s; + clk0 <= clk0_s after 10 ps; -- fix delta delay + rst0_out <= rst0; + +------------------------------------------------------------------------------------------------------------------------------------------------ +inst_sdram_clk : entity work.sdram_clk + GENERIC MAP + ( + clk_in_freq => F_SDRCLK, + clk0_out_phaseshift => 0, + clk1_out_phaseshift => 0 + ) + 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 + clk0_0_out => clk0_s, -- System clock #0, dcm#0 output 0° + clk0_270_out => open, -- System clock #0, dcm#0 output 270° + clk1_0_out => open, -- System clock #1 (e.g. clock for DDR-SDRAM data capture), dcm#1 output 0° + clk1_270_out => open, -- System clock #1 (e.g. clock for DDR-SDRAM data capture), dcm#1 output 270° + locked_out => locked, -- DCM locked status + error_out => error + ); + + clk_wr <= clk0_s; + clk_rd <= clk0_s; + +rst0_gen: + process(clk0) + begin + if rising_edge(clk0) then + rst0 <= not locked; + end if; + end process; + +------------------------------------------------------------------------------------------------------------------------------------------------ +utag_pipe: + process(clk0) + begin + if rising_edge(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) <= phy_ctrl.u_tag; + end if; + end if; + end process; + +WE_REGISTER: + process(clk0) + begin + if rising_edge(clk0) then + if rst0 = '1' then + we_reg <= '0'; + else + we_reg <= phy_ctrl.we; + end if; + end if; + end process; + +DATA_DRIVE_GEN: + process(clk0) + begin + if falling_edge(clk0) then + drive <= we_reg; + end if; + end process; + +DQS_DRIVE_GEN: + process(clk0) + variable p : unsigned(1 downto 0); + begin + if rising_edge(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; + end process; + +------------------------------------------------------------------------------------------------------------------------------------------------ +-- SDRAM Clock +part_clk <= clk0; + +------------------------------------------------------------------------------------------------------------------------------------------------ +-- Data OUT FFs + process (clk_wr) is + begin + if falling_edge(clk_wr) then + part_data <= (others => 'Z'); + if (drive = '1') then + part_data <= phy_in.wr_data; + end if; + end if; + end process; + +------------------------------------------------------------------------------------------------------------------------------------------------ +-- Data-mask OUT DDR-FFs + process (clk_wr) is + begin + if falling_edge(clk_wr) then + part_dqm <= phy_in.wr_dm; + end if; + end process; + +------------------------------------------------------------------------------------------------------------------------------------------------ + process (clk0) is + begin + if rising_edge(clk0) then + if rst0 = '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'; + else + part_ctrl_reg <= phy_ctrl.part; + end if; + end if; + end process; + + process (clk0) is + begin + if falling_edge(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 +----------------------------------------------------------------- +data_sample_stage: + process (clk0) + begin + if falling_edge(clk0) then + data_reg_r <= part_data; + end if; + end process; + +misc_flags_and_data_out: + process (clk0) + variable p : unsigned(3 downto 0); + begin + if rising_edge(clk0) then + if rst0 = '1' then + p := (others => '0'); + read_en <= '0'; + phy_out.rd_data_we <= '0'; + phy_out.wr_data_re <= '0'; + else + phy_out.rd_data <= data_reg_r; + if p(3) = '1' then + phy_out.tag_rd <= u_tag_pipe(4); + end if; + if phy_ctrl.we = '1' then + phy_out.tag_wr <= u_tag_pipe(0); + end if; + phy_out.wr_data_re <= phy_ctrl.we; + phy_out.rd_data_we <= 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 if; + end process; + +------------------------------------------------------------------------------------------ +end tech; diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdram_config_mt48lc16m16.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_config_mt48lc16m16.vhd new file mode 100644 index 0000000..f397a38 --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_config_mt48lc16m16.vhd @@ -0,0 +1,79 @@ +------------------------------------------------------------------------- +-- 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 PART_DATA_WIDTH : positive := 16; -- External DDR-SDRAM Module data bus width + constant PART_ADDR_WIDTH : positive := 13; -- number of address lines to DDR-SDRAM Device/Module + constant PART_BANK_WIDTH : positive := 2; -- Number of BANK address lines of external DDR-SDRAM + constant PART_ROW_ADDR_WIDTH : positive := 13; -- + constant PART_COL_ADDR_WIDTH : positive := 9; -- + + constant PART_DQS_WIDTH : positive := PART_DATA_WIDTH / 8; -- Number of data strobe lines + constant PART_DM_WIDTH : positive := PART_DATA_WIDTH / 8; -- Number of Data Mask Lines + constant BUS_DATA_WIDTH : positive := PART_DATA_WIDTH; -- SDR => part data width + constant BUS_DM_WIDTH : positive := PART_DM_WIDTH; -- SDR => part data width + + 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.8125E3; -- [ns] + + -- These values are for your SDRAM part (see datasheet) + constant TCAS : positive := 2; -- CAS latency [clocks] + constant TRP : real := 20.0; -- precharge command period [ns] + constant TRAS : real := 45.0; -- active to precharge delay [ns] + constant TRFC : real := 75.0; -- auto refresh command period [ns] + constant TMRD : positive := 2; -- load mode register command cylce time [clocks] + constant TRCD : real := 20.0; -- active to read or write delay [ns] + constant TWR : real := 15.0; -- write recovery time [ns] + + constant PWR_UP_WAIT : real := 1.0E3; -- [ns] + + subtype user_tag_t is unsigned(3 downto 0); + + ---------------------------------------------------------------------------------------------- + +end sdram_config; diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb16.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb16.vhd new file mode 100644 index 0000000..3ae2d90 --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb16.vhd @@ -0,0 +1,235 @@ +------------------------------------------------------------------------- +-- 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_wb16 is + Generic + ( + BURST_LEN : natural := 2; + F_SYSCLK : real := 100.0; + F_SDRCLK : real := 100.0; + FIFO_DEPTH : integer := 4 + ); + Port + ( + RST_I : in STD_LOGIC; + CLK_I : in STD_LOGIC; + SDRAM_RST0 : in STD_LOGIC; + SDRAM_CLK0 : 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; + MRDY_I : in STD_LOGIC; + SRDY_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); + + -- PHY interface + phy_ctrl : out phy_ctrl_t; + phy_in : out phy_in_t; + phy_out : in phy_out_t + + ); +end sdram_ctrl_frontend_wb16; + +architecture struct of sdram_ctrl_frontend_wb16 is + + signal u_addr : user_addr_t; + signal u_tag_in : user_tag_t; + signal u_cmd : user_cmd_t; + signal u_cmd_we : std_logic; + signal u_busy : std_logic; + signal rdy : std_logic; + + constant CAT_FIFO_WIDTH : integer := user_cmd_t'length + user_tag_t'length + PART_ROW_ADDR_WIDTH + PART_BANK_WIDTH + PART_COL_ADDR_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 write_fifo_din : unsigned(BUS_DATA_WIDTH + BUS_DM_WIDTH-1 downto 0); + signal write_fifo_dout : unsigned(BUS_DATA_WIDTH + BUS_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 read_fifo_din : unsigned(BUS_DATA_WIDTH-1 downto 0); + signal read_fifo_dout : unsigned(BUS_DATA_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; + + 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 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 0); + + alias write_fifo_data_in is write_fifo_din(write_fifo_din'length-1 downto BUS_DM_WIDTH); + alias write_fifo_dm_in is write_fifo_din(BUS_DM_WIDTH-1 downto 0); + alias write_fifo_data_out is write_fifo_dout(write_fifo_dout'length-1 downto BUS_DM_WIDTH); + alias write_fifo_dm_out is write_fifo_dout(BUS_DM_WIDTH-1 downto 0); + + alias read_fifo_data_in is read_fifo_din(read_fifo_din'length-1 downto 0); + alias read_fifo_data_out is read_fifo_dout(read_fifo_dout'length-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_async + GENERIC MAP + ( + addr_width => FIFO_DEPTH, + data_width => write_fifo_din'length + ) + PORT MAP + ( + rst => SDRAM_RST0, + clk_w => CLK_I, + clk_r => SDRAM_CLK0, + 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_async + GENERIC MAP + ( + addr_width => FIFO_DEPTH, + data_width => read_fifo_din'length + ) + PORT MAP + ( + rst => SDRAM_RST0, + clk_w => SDRAM_CLK0, + clk_r => 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_top : entity work.sdram_ctrl_top + Generic map + ( + BURST_LEN => BURST_LEN, + F_SYSCLK => F_SYSCLK, + F_SDRCLK => F_SDRCLK, + FIFO_DEPTH => FIFO_DEPTH + ) + Port map + ( + + sys_rst_in => RST_I, + sys_clk_in => CLK_I, + + sdram_rst0 => SDRAM_RST0, + sdram_clk0 => SDRAM_CLK0, + + -- User interface + u_tag => u_tag_in, + u_busy => u_busy, + u_addr => u_addr, + u_cmd => u_cmd, + u_cmd_we => u_cmd_we, + + -- Phy control interface + phy_ctrl => phy_ctrl + + ); + +------------------------------------------------------------------------------------------ + SRDY_O <= rdy; + ACK_O <= not (read_fifo_empty); + DAT_O <= read_fifo_data_out & read_fifo_data_out; + rdy <= not (cat_fifo_full or write_fifo_full or read_fifo_full) and CYC_I; + write_fifo_we <= STB_I and WE_I and rdy; + write_fifo_data_in <= DAT_I(15 downto 0); + write_fifo_dm_in <= not SEL_I(1 downto 0); + cat_fifo_we <= STB_I and rdy; + cmd_fifo_in <= UCMD_WRITE when WE_I = '1' else UCMD_READ; + addr_fifo_in <= ADDR_I(24 downto 2) & "0"; + tag_fifo_in <= "000" & ADDR_I(25); + + u_cmd_we <= (not cat_fifo_empty) and (not u_busy); + u_cmd <= cmd_fifo_out; + u_addr <= addr_fifo_out; + phy_in.wr_dm <= write_fifo_dm_out; + u_tag_in <= tag_fifo_out; + phy_in.wr_data <= write_fifo_data_out; + + write_fifo_re <= phy_out.wr_data_re and (not write_fifo_empty); + cat_fifo_re <= u_cmd_we; + read_fifo_re <= (not read_fifo_empty) and MRDY_I; + read_fifo_we <= phy_out.rd_data_we; + read_fifo_data_in <= phy_out.rd_data; + +end architecture struct; diff --git a/lib/SDRAM/ddr_sdr_v1_5/src/tb_ctrl_sdr_wb32.vhd b/lib/SDRAM/ddr_sdr_v1_5/src/tb_ctrl_sdr_wb32.vhd new file mode 100644 index 0000000..13aae96 --- /dev/null +++ b/lib/SDRAM/ddr_sdr_v1_5/src/tb_ctrl_sdr_wb32.vhd @@ -0,0 +1,834 @@ +------------------------------------------------------------------------- +-- 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.sdram_config.all; +use work.sdram_types.all; + +entity tb_ctrl_sdr_wb32 is +end; + +architecture struct of tb_ctrl_sdr_wb32 is + + constant CLK_PERIOD : time := 10 ns; + constant SDCLK_PERIOD : time := 10 ns; + constant BURST_LEN : natural := 2; + + signal sdclk : std_logic := '1'; + signal sdclk_fb : std_logic; + signal part_clk : 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(PART_BANK_WIDTH-1 downto 0) := (others => '0'); + signal part_dqm : unsigned(PART_DM_WIDTH-1 downto 0) := (others => '0'); + signal part_addr : unsigned(PART_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal part_data : unsigned(PART_DATA_WIDTH-1 downto 0) := (others => '0'); + + signal CLK_O : std_logic := '1'; + signal RST_O : std_logic := '1'; + 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 MRDY_O : std_logic := '1'; + signal SRDY_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; + + type sd_cmd_t is (nop, lmr, ar, pre, act, write, read, bst); + signal sd_cmd : sd_cmd_t; + +begin + + process(part_cs_n, part_ras_n, part_cas_n, part_we_n) + variable cmd : unsigned (2 downto 0); + + begin + cmd := part_ras_n & part_cas_n & part_we_n; + sd_cmd <= nop; + if part_cs_n = '0' then + case cmd is + when "000" => + sd_cmd <= lmr; + when "001" => + sd_cmd <= ar; + when "010" => + sd_cmd <= pre; + when "011" => + sd_cmd <= act; + when "100" => + sd_cmd <= write; + when "101" => + sd_cmd <= read; + when "110" => + sd_cmd <= bst; + when "111" => + sd_cmd <= nop; + + when others => + sd_cmd <= nop; + + end case; + end if; + end process; + + sdclk_fb <= part_clk after 1 ns; + + -- DDR SDRAM Controller Core + uut : entity work.ctrl_sdr_wb32 + GENERIC MAP + ( + BURST_LEN => BURST_LEN, + F_SYSCLK => 100.000, + F_SDRCLK => 100.000, + FIFO_DEPTH => 4 + ) + PORT MAP + ( + RST_I => RST_O, + CLK_I => CLK_O, + SDRAM_CLK_I => sdclk, + SDRAM_CLK_FB_I => sdclk_fb, + + CYC_I => CYC_O, + STB_I => STB_O, + SEL_I => SEL_O, + WE_I => WE_O, + ACK_O => ACK_I, + SRDY_O => SRDY_I, + MRDY_I => MRDY_O, + ADDR_I => ADDR_O, + DAT_I => DAT_O, + DAT_O => DAT_I, + + -- SDRAM signals + sd_clk => part_clk, + 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_dqm => part_dqm, + sd_data => part_data + + ); + + -- MICRON DDR SDRAM Simulation Model + -- 4M x16x4 Banks + -- IS42S16160B-7 +i_mt48lc16m16_0 : entity work.mt48lc16m16a2 + generic map + ( + tAC => 6.5 ns, + tHZ => 5.4 ns, + tOH => 2.7 ns, + tMRD => 2, -- 2 Clk Cycles + tRAS => 45.0 ns, + tRC => 67.5 ns, + tRCD => 20.0 ns, + tRP => 20.0 ns, + tRRD => 14.0 ns, + tAH => 0.8 ns, + tAS => 1.5 ns, + tCH => 0.8 ns, + tCL => 2.5 ns, + tCK => 10.0 ns, + tDH => 0.8 ns, + tDS => 1.5 ns, + tCKH => 0.8 ns, + tCKS => 1.5 ns, + tCMH => 0.8 ns, + tCMS => 1.5 ns + ) + port map + ( + unsigned(Dq) => std_logic_vector(part_data), + Addr => std_logic_vector(part_addr), + Ba => std_logic_vector(part_ba), + Clk => part_clk, + Cke => part_cke, + Cs_n => part_cs_n, + Ras_n => part_ras_n, + Cas_n => part_cas_n, + We_n => part_we_n, + Dqm => std_logic_vector(part_dqm) + ); + +CLK_GEN: process + begin + wait for CLK_PERIOD/2; + CLK_O <= not CLK_O; + end process; + +SDCLK_GEN: process + begin + wait for SDCLK_PERIOD/2; + sdclk <= not sdclk; + 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_O <= '0'; + + wait until RST_O = '0'; + -- 8 single cycles + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + DAT_O <= X"0000_1234"; + ADDR_O <= X"0000_0000"; + + for i in 0 to 8192 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + ------------------------------------------------------------ + wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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"; + + for i in 0 to 31 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 31; + 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"0000_BEEF"; + wait until rising_edge(CLK_O) and SRDY_I = '1'; + STB_O <= '0'; + wait until rising_edge(CLK_O); + 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 SRDY_I = '1'; + STB_O <= '0'; + wait until rising_edge(CLK_O) and ACK_I = '1'; + CYC_O <= '0'; + + ------------------------------------------------------------ + wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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"; + + for i in 0 to 31 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 31; + CYC_O <= '0'; + + ------------------------------------------------------------ + wait for 10*CLK_PERIOD; + ------------------------------------------------------------ + + for k in 0 to 3 loop + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_0400"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_0800"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_0C00"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + end loop; + + ------------------------------------------------------------ + wait for 10*CLK_PERIOD; + ------------------------------------------------------------ + + for k in 0 to 3 loop + + -- 8-word burst cycle + 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_1000"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_1400"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_1800"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_1C00"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + end loop; + + ------------------------------------------------------------ + wait for 10*CLK_PERIOD; + ------------------------------------------------------------ + + for k in 0 to 3 loop + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + dout_rst <= '1'; + wait until rising_edge(CLK_O); + dout_rst <= '0'; + + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + SEL_O <= "1111"; + DAT_O <= X"0000_1111"; + ADDR_O <= X"0000_0000"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + dout_rst <= '1'; + wait until rising_edge(CLK_O); + dout_rst <= '0'; + + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + SEL_O <= "1111"; + DAT_O <= X"0000_2222"; + ADDR_O <= X"0000_0400"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + dout_rst <= '1'; + wait until rising_edge(CLK_O); + dout_rst <= '0'; + + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + SEL_O <= "1111"; + DAT_O <= X"0000_3333"; + ADDR_O <= X"0000_0800"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + dout_rst <= '1'; + wait until rising_edge(CLK_O); + dout_rst <= '0'; + + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + SEL_O <= "1111"; + DAT_O <= X"0000_4444"; + ADDR_O <= X"0000_0C00"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + end loop; + + ------------------------------------------------------------ + wait for 10*CLK_PERIOD; + ------------------------------------------------------------ + + for k in 0 to 3 loop + + -- 8-word burst cycle + dout_rst <= '1'; + wait until rising_edge(CLK_O); + dout_rst <= '0'; + + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + SEL_O <= "1111"; + DAT_O <= X"0000_1111"; + ADDR_O <= X"0000_1000"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + dout_rst <= '1'; + wait until rising_edge(CLK_O); + dout_rst <= '0'; + + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + SEL_O <= "1111"; + DAT_O <= X"0000_2222"; + ADDR_O <= X"0000_1400"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + dout_rst <= '1'; + wait until rising_edge(CLK_O); + dout_rst <= '0'; + + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + SEL_O <= "1111"; + DAT_O <= X"0000_3333"; + ADDR_O <= X"0000_1800"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + dout_rst <= '1'; + wait until rising_edge(CLK_O); + dout_rst <= '0'; + + CYC_O <= '1'; + STB_O <= '1'; + WE_O <= '1'; + SEL_O <= "1111"; + DAT_O <= X"0000_4444"; + ADDR_O <= X"0000_1C00"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + DAT_O <= DAT_O + 1; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O); + CYC_O <= '0'; + + end loop; + + ------------------------------------------------------------ + wait for 10*CLK_PERIOD; + ------------------------------------------------------------ + + for k in 0 to 3 loop + + -- 8-word burst cycle + 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_1000"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_1400"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_1800"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + ------------------------------------------------------------ +-- wait for 3*CLK_PERIOD; + ------------------------------------------------------------ + + -- 8-word burst cycle + 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_1C00"; + + for i in 0 to 7 loop + wait until rising_edge(CLK_O) and SRDY_I = '1'; + ADDR_O <= ADDR_O + 4; + end loop; + + STB_O <= '0'; + wait until rising_edge(CLK_O) and dout_cnt = 7; + CYC_O <= '0'; + + end loop; + + wait; + + end process; + +end architecture struct;