Access to SDRAM on Altera Cyclone dev kit - compactflash con
CASTalk.com Forum Index CASTalk.com
Discussion of DSP, FPGA, storage and embedded system.
 
 FAQFAQ   MemberlistMemberlist     RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Google
 
Web castalk.com
Access to SDRAM on Altera Cyclone dev kit - compactflash con

 
Post new topic   Reply to topic    CASTalk.com Forum Index -> FPGA
Author Message
fanf
Guest





Posted: Mon Dec 20, 2004 10:57 pm    Post subject: Access to SDRAM on Altera Cyclone dev kit - compactflash con Reply with quote

Hello,

(I'm a beginner in vhdl programmation, so excuse me if my questions seem
trivial.)

I have to create a VHDL design witch runs on altera's cyclone FPGA. To
do that, I use your microtronix dev board, but not the SOPC builder
components.
The goal of the design is to create a data storage box, a kind of hard
disk where the disk is replaced by some SDRAM and a Compact Flash Card.

Does somebody know where I could find doc about this topic ? I mean, doc
about making a controller for a Compact Flash Card (it should have be
done yet),
managing read/write between flash card/sdram/controller of the
datastorage in an efficient way, etc.

I also want to be able to read/write in SDRAM and for that, I use the
Altera's SDRAM controller found here :
http://www.altera.com/products/ip/iup/memory/m-alt-sdr-sdram.html
I create a state machine to interface the SDRAM's controller and the
others part of the design. This state machine manages sdram
initialisation, and read/write queries.
All simulations work fine, but when I load my code on the board, it does
not work.
I thought it was a problem with the use of onboard clocks, but it seems
that there is something else : an other design which only made two write
statement and then alternatively read each one works fine.
I really don't know what might be the source of the problem, so what are
the things I have to check ? Are there frequently done mistakes in using
this SDRAM controller ? (I join my broken code and the working one)

I also want to split my big state machine in several parts which are
semantically consistant : one for the init, an other for reading
queries, etc. And I don't know how to
handle this problem. What is 'the right way' to do this in vhdl ?

Many thanks


--------------------------------------------------------------------------------
Working design
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY sdramInit IS
GENERIC (
NOP_TIME : integer := 2;
CONSTANT C_NOP : std_logic_vector (2 DOWNTO 0) := "000";
CONSTANT C_PRECHARGE : std_logic_vector (2 DOWNTO 0) := "100";
CONSTANT C_REFRESH : std_logic_vector (2 DOWNTO 0) := "011";
CONSTANT C_LOAD_MODE : std_logic_vector (2 DOWNTO 0) := "101";
CONSTANT C_LOAD_REG1 : std_logic_vector (2 DOWNTO 0) := "110";
CONSTANT C_LOAD_REG2 : std_logic_vector (2 DOWNTO 0) := "111"
);
PORT (
clk : IN std_logic;
data_to_mp : IN std_logic_vector (31 DOWNTO 0);
rst_1 : IN std_logic;
ack_to_mp : IN std_logic;
data_to_sd : OUT std_logic_vector (31 DOWNTO 0);
cmd_to_sd : OUT std_logic_vector (2 DOWNTO 0);
adresse_to_sd : OUT std_logic_vector (22 DOWNTO 0);
dm_to_sd : OUT std_logic_vector (3 DOWNTO 0);
data_to_7seg : OUT std_logic_vector (6 DOWNTO 0);
led1 : OUT std_logic;
led2 : OUT std_logic);

END sdramInit;


ARCHITECTURE archi OF sdramInit IS
TYPE TYPE_STATE IS (reset,
nop,
precharge, prechargeNop,
loadmode, loadmodeNop,
load_reg2, load_reg2Nop,
load_reg1, load_reg1Nop,
refresh1,
refresh2,
ecriture,
ecriture2,
lecture,
lecture2,
fin,
wait1,
wait2,
wait0,
fetch1,
fetch2,
nopn,
nopn1,
nopn2,
nopn3);
SIGNAL etat : TYPE_STATE;
SIGNAL counter : integer RANGE 0 TO 255;
signal nccounter : integer range 0 to 100000000;

BEGIN -- archi

PROCESS (clk, rst_1)
BEGIN -- PROCESS
IF rst_1 = '0' THEN -- asynchronous reset (active low)
etat <= reset;
cmd_to_sd <= C_NOP;
adresse_to_sd <= "00000000000000000000000";
data_to_sd <= "00000000000000000000000000000000";
dm_to_sd <= "1100";
counter <= 0;
led1 <= '0';
led2 <= '0';
nccounter <= 0;
ELSIF clk'event AND clk = '1' THEN -- rising clock edge

CASE etat IS
WHEN reset => etat <= nop;
counter <= 0;
WHEN nop => cmd_to_sd <= C_NOP;
IF counter = NOP_TIME THEN
etat <= precharge;
counter <= 0;
ELSE
etat <= nop;
counter <= counter + 1;
END IF;
WHEN precharge => IF ack_to_mp = '1' THEN
etat <= prechargeNop;
ELSE
cmd_to_sd <= C_PRECHARGE;
etat <= precharge;
END IF;
WHEN prechargeNop => cmd_to_sd <= C_NOP;
etat <= loadmode;
WHEN loadmode => IF ack_to_mp = '1' THEN
etat <= loadmodeNop;
ELSE
cmd_to_sd <= C_LOAD_MODE;
adresse_to_sd <= "00000000000001000010000";
-- a10 : reserved = 0
-- a9 : Write Burst = 1 (single location access)
-- a8-7 : Op mode 00
-- a6-4 : CAS latency : 001 ( 1 )
-- a3 : BT 0 ( sequential )
-- a2-0 : busrt length 000 ( 1 )
etat <= loadmode;
END IF;
WHEN loadmodeNop => cmd_to_sd <= C_NOP;
etat <= load_reg2;
WHEN load_reg2 => IF ack_to_mp = '1' THEN
etat <= load_reg1;
ELSE
cmd_to_sd <= C_LOAD_REG2;
-- adresse_to_sd <= "00000000000011000011010"; -- 1562 c'est pour
100 MHz
adresse_to_sd <= "00000000000001000000000"; -- 521 c'est pour 33
MHz

etat <= load_reg2;
END IF;
-- WHEN load_reg2Nop => cmd_to_sd <= C_NOP;
-- etat <= load_reg1;
WHEN load_reg1 => IF ack_to_mp = '1' THEN
etat <= refresh1;
ELSE
cmd_to_sd <= C_LOAD_REG1;
-- adresse_to_sd <= "00000000000001001101101"; -- old value
adresse_to_sd <= "00000000000001000101001";
-- a12-9 : burst lenght : 0001
-- a8 : sdram controller mode : 0 (normal)
-- a7-4 : refresh command duration in clocks ???? t rrd = 14 ns
/ 30 ns
-- a3-2 : ras to cas in number of clocks ??? trcd = 20 ns / 30
ns ? -- bizarrement, marche bcp mieux avec une valeur de 2
-- a1-0 : cas latency : 1
etat <= load_reg1;
END IF;
-- WHEN load_reg1Nop => cmd_to_sd <= C_NOP;
-- etat <= refresh1;
WHEN refresh1 => IF ack_to_mp = '1' THEN
cmd_to_sd <= C_NOP;
etat <= refresh2;
ELSE
cmd_to_sd <= C_REFRESH;
etat <= refresh1;
END IF;
WHEN refresh2 => IF ack_to_mp = '1' THEN
cmd_to_sd <= C_NOP;
etat <= nopn;
ELSE
cmd_to_sd <= C_REFRESH;
etat <= refresh2;
END IF;
when nopn => cmd_to_sd <="000";
etat <= nopn1;

when nopn1 => cmd_to_sd <="000";
etat <= nopn2;
when nopn2 => cmd_to_sd <="000";
etat <= nopn3;
when nopn3 => cmd_to_sd <="000";
etat <= ecriture;

WHEN ecriture => cmd_to_sd <= "010";
data_to_sd <= "00000000000000000000000011111001";
adresse_to_sd <= "00000000000000000000000";
IF ack_to_mp = '1' THEN
etat <= wait0;
ELSE
etat <= ecriture;
END IF;
WHEN wait0 => cmd_to_sd <= "000";


if nccounter<9 then
nccounter <= nccounter +1;
etat <= wait0;
else
nccounter <= 0;
etat <= ecriture2;
end if;
WHEN ecriture2 => cmd_to_sd <= "010";
data_to_sd <= "00000000000000000000000000001111";
adresse_to_sd <= "00000000000000000000001";
IF ack_to_mp = '1' THEN
etat <= wait2;
ELSE
etat <= ecriture2;
END IF;
WHEN lecture => cmd_to_sd <= "001";
led1 <= '1';
led2 <= '0';
adresse_to_sd <= "00000000000000000000000";
IF ack_to_mp = '1' THEN

etat <= fetch1;
ELSE
etat <= lecture;
END IF;

WHEN fetch1 =>cmd_to_sd <= "000";
-- wait RCD + CL + 2 = 1 + 20 ns + 2clk = 3 clk
if nccounter<2 then
nccounter <= nccounter +1;
etat <= fetch1;
else
data_to_7seg <= data_to_mp (6 DOWNTO 0);
nccounter <= 0;
etat <= wait1;
end if;


WHEN wait1 =>
if nccounter<4000000 then
nccounter <= nccounter +1;
etat <= wait1;
else
nccounter <= 0;

etat <= lecture2;
end if;

WHEN lecture2 => cmd_to_sd <= "001";
led1 <= '0';
led2 <= '1';
adresse_to_sd <= "00000000000000000000001";
IF ack_to_mp = '1' THEN
-- data_to_7seg <= data_to_mp (6 DOWNTO 0);
etat <= fetch2;
ELSE
etat <= lecture2;
END IF;
WHEN fetch2 =>cmd_to_sd <= "000";
-- wait RCD + CL + 2 = 1 + 20 ns + 2clk = 3 clk
if nccounter<2 then
nccounter <= nccounter +1;
etat <= fetch2;
else
data_to_7seg <= data_to_mp (6 DOWNTO 0);
nccounter <= 0;
etat <= wait2;
end if;

WHEN wait2 =>
cmd_to_sd <= "000";
if nccounter<4000000 then
nccounter <= nccounter +1;
etat <= wait2;
else
nccounter <= 0;
etat <= lecture;
end if;

WHEN fin => etat <= fin;
WHEN OTHERS => NULL;
END CASE;
END IF;
END PROCESS;

END archi;

---------------------------------------------------------------------------------
My design
---------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;


-- Module SdramInterface

-- Fonctionnal description :
-- this module is an interface between the sdram controller and others
parts
-- of the design (say "ext").
-- Its goal is to manage sdram initialisation and read/write queries.
-- It implements a state machine with 4 main states :
-- - initialisation of the SDRAM,
-- - wait for a command,
-- - write on SDRAM and
-- - read on SDRAM

ENTITY sdramInterface is
GENERIC (

-- command to the SDRAM controller
CONSTANT C_NOP : std_logic_vector (2 DOWNTO 0) := "000";
CONSTANT C_init_precharge : std_logic_vector (2 DOWNTO 0) := "100";
CONSTANT C_REFRESH : std_logic_vector (2 DOWNTO 0) := "011";
CONSTANT C_init_load_mode : std_logic_vector (2 DOWNTO 0) := "101";
CONSTANT C_init_load_reg1 : std_logic_vector (2 DOWNTO 0) := "110";
CONSTANT C_init_load_reg2 : std_logic_vector (2 DOWNTO 0) := "111";
constant C_WRITEA : std_logic_vector (2 DOWNTO 0) := "010";
constant C_READEA : std_logic_vector (2 DOWNTO 0) := "001";

-- commands from/to ext
constant READ_OK : std_logic_vector (1 DOWNTO 0) := "01";
constant READ_MODE : std_logic_vector (1 DOWNTO 0) := "01";
constant WRITE_OK : std_logic_vector (1 DOWNTO 0) := "10";
constant WRITE_MODE : std_logic_vector (1 DOWNTO 0) := "10";

-- Parameter of the sdram
constant ASIZE : integer := 23; -- adress size
constant DSIZE : integer := 32; -- data size
constant DSIZE_sur_8 : integer := 4; -- data mask size
constant BL : integer := 1; --burst lengh
constant TL_W : integer := 1; --latence time on a write command
constant TL_R : integer := 4; --latence time on a read command

-- conf of sdram chip (load_mode command)
-- a10 : reserved : 0
-- a9 : Write Burst : 0
-- a8-7 : op mode : 00
-- a6-4 : CAS latency : 001 ( 1 )
-- a3 : BT : 0 ( sequential )
-- a2-0 : busrt length : 000 ( 1 )
constant CONF_init_load_mode : std_logic_vector (22 downto 0) :=
"00000000000000000010000";

-- Config of REG1 : altera controller parameter
-- a12-9 : burst lenght : 0001
-- a8 : sdram controller mode : 0 (normal)
-- a7-4 : refresh command duration in clocks : t(rrd)/clock period =
14 ns / 30.5 ns = 1 (??)
-- a3-2 : ras to cas (rcd) in number of clocks : t(rcd)/clock period
= 20 ns / 30.5 ns (? idem, 1 ?)
-- a1-0 : cas latency : 01
constant CONF_REG1 : std_logic_vector (22 downto 0) :=
"00000000000001000101001";


-- Config de REG2 : period beetwin refresh
-- value is obtained by the calcul 15.625us/T, where T is clock period
(in micro second)
-- constant CONF_REG2 : std_logic_vector (ASIZE-1 downto 0) :=
"00000000000011000011010" -- 1562 when clock= 100 MHz, T = 0.01 us
constant CONF_REG2 : std_logic_vector (22 downto 0) :=
"00000000000001000000000" -- 512 when clock= 32.768 MHz, T = .0305us

);

PORT (
-- NOTATION :
-- what is transfered to ext is prefixed by _ext_
-- what is transfered to the controller is prefixed by _cont_
clk : IN std_logic;
rst_n : IN std_logic;
-- to/from extr
i_ext_donnees : IN std_logic_vector (DSIZE-1 DOWNTO 0); --data from
ext (data to write on SDRAM)
i_ext_masqueEcriture : std_logic_vector (DSIZE_sur_8 - 1 downto 0);
--data mask
i_ext_adresse : in std_logic_vector (ASIZE-1 downto 0); --adress
i_ext_demande_rw : in std_logic_vector (1 downto 0); --ext queries
o_ext_donnees : OUT std_logic_vector (DSIZE-1 DOWNTO 0); --data to
ext (data read from SDRAM)
o_ext_sdram_ready : OUT std_logic; --wait for read/write
o_ext_rw_ok : out std_logic_vector (1 downto 0); -- ack read/write
o_ext_erreur : out std_logic; --error
-- to/from the controller
i_cont_donnees : IN std_logic_vector (DSIZE-1 DOWNTO 0); -- data
from the controller (data read on SDRAM)
i_cont_accuseCommande : IN std_logic; -- command to controller ack
o_cont_donnees : OUT std_logic_vector (DSIZE-1 DOWNTO 0); -- data
to the controller (data to write on SDRAM)
o_cont_commande : OUT std_logic_vector (2 DOWNTO 0); -- command to
the controller
o_cont_adresse : OUT std_logic_vector (ASIZE-1 DOWNTO 0); -- adress
o_cont_masqueEcriture : OUT std_logic_vector (DSIZE_sur_8 - 1
DOWNTO 0) -- mask

);

end sdramInterface;

--/////////////////////////////////////////////////////////////////////////////////////////////////////////////--


ARCHITECTURE archi OF sdramInterface is

type type_etatProcessPrincipal is (
etat_reset, etat_erreur,
-- init states
init_attente_stab,
init_precharge, init_prechargeNop,
init_load_mode, init_load_modeNop,
init_load_reg1, init_load_reg2,
init_refresh1, init_refresh2,
init_2nop,
-- wait command state
etat_attente_instruction,
-- read states
ecriture_init,
ecriture_attente_latence,
ecriture_boucle_donnees,
-- write states
lecture_init,
lecture_attente_latence,
lecture_boucle_donnees
);
signal etat_suivant : type_etatProcessPrincipal;

signal compteur_ecriture : integer range 0 to TL_W; -- write latence
counter
signal compteur_lecture : integer range 0 to TL_R; --read latence counter
signal compteur_bl : integer range 0 to BL; -- burst lenght counter
signal i : integer range 0 to 3000; -- init counter

-- register
signal reg_o_ext_donnees : std_logic_vector (DSIZE-1 downto 0);
signal reg_o_cont_donnees : std_logic_vector (DSIZE-1 downto 0);
signal reg_o_cont_masqueecriture : std_logic_vector (3 downto 0);
signal reg_o_cont_adresse : std_logic_vector (ASIZE-1 downto 0);

BEGIN -- archi

process (clk, rst_n)

variable num_ecriture : std_logic;

begin
if rst_n = '0' then -- asynchronous reset, active low
etat_suivant <= init_attente_stab;
compteur_ecriture <= 0;
compteur_lecture <= 0;
compteur_bl <= 0;
i <= 0;
--to/from cont
o_cont_commande <= C_NOP;
reg_o_cont_adresse <= (others => '0');
reg_o_cont_donnees <= (others => '0');
reg_o_cont_masqueEcriture <= (others => '0');
--to/from ext
reg_o_ext_donnees <= (others => '0');
o_ext_rw_ok <= "00";
elsif clk'event and clk = '1' then

case etat_suivant is

--*******************************************************************************************

-- State to manage the micron SDRAM chip and altera controller
--
-- o_cont_adresse is the bus to pass the config parameter
--*******************************************************************************************


when init_attente_stab =>
o_cont_commande <= C_NOP;
if i < 3000 then --wait 100 us, ie 30*100 clk
o_cont_commande <= C_NOP;
i <= i + 1;
etat_suivant <= init_attente_stab;
else
etat_suivant <= init_precharge;
end if;

when init_precharge =>
if i_cont_accuseCommande = '1' then
o_cont_commande <= C_NOP;
etat_suivant <= init_prechargeNop;
else
o_cont_commande <= C_init_precharge;
etat_suivant <= init_precharge;
end if;

when init_prechargeNop =>
o_cont_commande <= C_NOP;
etat_suivant <= init_load_mode;

when init_load_mode =>
if i_cont_accuseCommande = '1' then
o_cont_commande <= C_NOP;
etat_suivant <= init_load_modeNop;
else
o_cont_commande <= C_init_load_mode;
reg_o_cont_adresse <= CONF_init_load_mode;
etat_suivant <= init_load_mode;
end if;

when init_load_modeNop =>
o_cont_commande <= C_NOP;
etat_suivant <= init_load_reg2;

when init_load_reg2 =>
if i_cont_accuseCommande = '1' then
o_cont_commande <= C_NOP;
etat_suivant <= init_load_reg1;
else
o_cont_commande <= C_init_load_reg2;
reg_o_cont_adresse <= CONF_REG2;
etat_suivant <= init_load_reg2;
end if;

when init_load_reg1 =>
if i_cont_accuseCommande = '1' then
o_cont_commande <= C_NOP;
etat_suivant <= init_refresh1;
else
o_cont_commande <= C_init_load_reg1;
reg_o_cont_adresse <= CONF_REG1;
etat_suivant <= init_load_reg1;
end if;

when init_refresh1 =>
if i_cont_accuseCommande = '1' then
o_cont_commande <= C_NOP;
etat_suivant <= init_refresh2;
else
o_cont_commande <= C_REFRESH;
etat_suivant <= init_refresh1;
end if;

when init_refresh2 =>
if i_cont_accuseCommande = '1' then
o_cont_commande <= C_NOP;
etat_suivant <= init_2nop;
i <= 0;
else
o_cont_commande <= C_REFRESH;
etat_suivant <= init_refresh2;
end if;

when init_2nop =>
o_cont_commande <= C_NOP;
if i < 2 then
i <= i + 1;
etat_suivant <= init_2nop;
else
i <= 0;
etat_suivant <= etat_attente_instruction;
end if;

--*******************************************************************************

-- wait state : nothing is done until a read or write command is done
by ext.
--*******************************************************************************


when etat_attente_instruction =>
o_cont_commande <= C_NOP;
reg_o_cont_adresse <= (others => 'X');
reg_o_cont_donnees <= (others => 'X');
reg_o_cont_masqueEcriture <= (others => 'X');
o_ext_rw_ok <= "00";

-- is there a new demand ?
case i_ext_demande_rw is
when READ_MODE =>
etat_suivant <= lecture_init;
when WRITE_MODE =>
etat_suivant <= ecriture_init;
when others =>
etat_suivant <= etat_attente_instruction;
end case;

--******************************************************************************************

-- states of a burst write
--******************************************************************************************


when ecriture_init =>
compteur_ecriture <= 0;
o_cont_commande <= C_WRITEA;
o_ext_rw_ok <= "00";

--register data
reg_o_cont_adresse <= i_ext_adresse;
reg_o_cont_donnees <= i_ext_donnees;
reg_i_ext_masque <= i_ext_masque;

if i_cont_accuseCommande = '1' then
o_cont_commande <= C_NOP;
etat_suivant <= ecriture_attente_latence;
else
etat_suivant <= ecriture_init;
end if;

-- wait for the write-latency
when ecriture_attente_latence =>
o_cont_commande <= C_NOP;

if compteur_ecriture < (TL_W - 1) then
compteur_ecriture <= compteur_ecriture + 1;
o_ext_rw_ok <= "00"; --not in burst loop
etat_suivant <= ecriture_attente_latence;
else
compteur_ecriture <= 0;
etat_suivant <= ecriture_boucle_donnees;
o_ext_rw_ok <= WRITE_OK;
compteur_bl <= 1; --first burst data is wrote
end if;

-- next words of the burst message, one word per clock tick
when ecriture_boucle_donnees =>
o_cont_commande <= C_NOP;
if compteur_bl < BL then
o_ext_rw_ok <= WRITE_OK;
etat_suivant <= ecriture_boucle_donnees;
compteur_bl <= compteur_bl + 1;
else --and of burst
o_ext_rw_ok <= "00";
etat_suivant <= etat_attente_instruction;
end if;
--- end of write burst states ---

--******************************************************************************************

-- state of a read burst
--******************************************************************************************


when lecture_init =>
compteur_lecture <= 0;
o_ext_rw_ok <= "00";
reg_o_cont_adresse <= i_ext_adresse;
o_cont_commande <= C_READEA;

if i_cont_accuseCommande = '1' then --now, only TL_R ticks remain.
o_cont_commande <= C_NOP;
compteur_lecture <= 0;
etat_suivant <= lecture_attente_latence;
else
etat_suivant <= lecture_init;
end if;

-- wait for the right number of ticks
when lecture_attente_latence =>
o_cont_commande <= C_NOP;
if compteur_lecture < (TL_R-1) then
compteur_lecture <= compteur_lecture + 1;
etat_suivant <= lecture_attente_latence;
o_ext_rw_ok <= "00";
else
reg_o_ext_donnees <= i_cont_donnees;
etat_suivant <= lecture_boucle_donnees;
o_ext_rw_ok <= READ_OK;
compteur_bl <= 1; --number 0 of the burst done
end if;

-- next words of the burst, one per clock tick.
when lecture_boucle_donnees =>
if compteur_bl < BL then
reg_o_ext_donnees <= i_cont_donnees;
o_ext_rw_ok <= READ_OK;
compteur_bl <= compteur_bl + 1;
etat_suivant <= lecture_boucle_donnees;
else
o_ext_rw_ok <= READ_OK;
etat_suivant <= etat_attente_instruction;
end if;
--- end of read burst states ---

when etat_erreur => etat_suivant <= etat_erreur;
when others => etat_suivant <= etat_erreur;

end case; --end of state machine
end if;
end process;

--***********************************************************************************

-- others parallel instructions
--***********************************************************************************


--error and ready signal to ext
o_ext_sdram_ready <= '1' when etat_suivant = etat_attente_instruction
else '0';
o_ext_erreur <= '0' when etat_suivant = etat_erreur else '1';


--registered outputs
o_cont_adresse <= reg_o_cont_adresse;
o_cont_donnees <= reg_o_cont_donnees;
o_cont_masqueEcriture <= reg_o_cont_masqueEcriture;

o_ext_donnees <= reg_o_ext_donnees;

end archi;
Back to top
 
Post new topic   Reply to topic    CASTalk.com Forum Index -> FPGA All times are GMT
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum




VoIP Electronics Powered by phpBB