Created
September 16, 2011 03:02
-
-
Save xesscorp/1221094 to your computer and use it in GitHub Desktop.
SDRAM interface test code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library IEEE; | |
use IEEE.STD_LOGIC_1164.all; | |
use IEEE.STD_LOGIC_ARITH.all; | |
use IEEE.STD_LOGIC_UNSIGNED.all; | |
use WORK.CommonPckg.all; | |
use work.ClkgenPckg.all; | |
use WORK.SdramCntlPckg.all; | |
library UNISIM; | |
use UNISIM.VComponents.all; | |
entity xula_sdram is | |
generic( | |
BASE_FREQ_G : real := 12.0; -- base frequency in MHz | |
CLK_MUL_G : natural := 25; -- multiplier for base frequency | |
CLK_DIV_G : natural := 3; -- divider for base frequency | |
PIPE_EN_G : boolean := false; | |
DATA_WIDTH_G : natural := 16; -- width of data | |
HADDR_WIDTH_G : natural := 23; -- host-side address width | |
SADDR_WIDTH_G : natural := 12; -- SDRAM address bus width | |
NROWS_G : natural := 4096; -- number of rows in each SDRAM bank | |
NCOLS_G : natural := 512; -- number of words in each row | |
-- beginning and ending addresses for the entire SDRAM | |
BEG_ADDR_G : natural := 16#00_0000#; | |
END_ADDR_G : natural := 16#7F_FFFF#; | |
-- beginning and ending address for the memory tester | |
BEG_TEST_G : natural := 16#00_0000#; | |
END_TEST_G : natural := 16#3F_FFFF# | |
); | |
port( | |
fpgaClk_i : in std_logic; -- main clock input from external clock source | |
sdClk_o : out std_logic; -- clock to SDRAM | |
sdClkFb_i : in std_logic; -- SDRAM clock comes back in | |
sdRas_bo : out std_logic; -- SDRAM RAS | |
sdCas_bo : out std_logic; -- SDRAM CAS | |
sdWe_bo : out std_logic; -- SDRAM write-enable | |
sdBs_o : out std_logic; -- SDRAM bank-address | |
sdAddr_o : out std_logic_vector(SADDR_WIDTH_G-1 downto 0); -- SDRAM address bus | |
sdData_io : inout std_logic_vector(DATA_WIDTH_G-1 downto 0); -- data bus to/from SDRAM | |
chan_io : inout std_logic_vector(5 downto 1) | |
); | |
end xula_sdram; | |
architecture Behavioral of xula_sdram is | |
constant FREQ_G : real := (BASE_FREQ_G * real(CLK_MUL_G)) / real(CLK_DIV_G); | |
signal clk : std_logic; | |
-- constant HADDR_WIDTH_G : natural := Log2(END_ADDR_G-BEG_ADDR_G+1); | |
signal rst_i : std_logic; -- internal reset signal | |
signal divCnt : unsigned(20 downto 0); -- clock divider | |
-- signals that go through the SDRAM host-side interface | |
signal begun : std_logic; -- SDRAM operation started indicator | |
signal earlyBegun : std_logic; -- SDRAM operation started indicator | |
signal done : std_logic; -- SDRAM operation complete indicator | |
signal rdDone : std_logic; -- SDRAM operation complete indicator | |
signal hAddr : std_logic_vector(HADDR_WIDTH_G-1 downto 0); -- host address bus | |
signal hDIn : std_logic_vector(DATA_WIDTH_G-1 downto 0); -- host-side data to SDRAM | |
signal hDOut : std_logic_vector(DATA_WIDTH_G-1 downto 0); -- host-side data from SDRAM | |
signal rd : std_logic; -- host-side read control signal | |
signal wr : std_logic; -- host-side write control signal | |
signal rdPending : std_logic; -- read operation pending in SDRAM pipeline | |
-- my new variables | |
type STATE_TYPE is (S_BEGIN, S_WAIT, S_READ, S_READWAIT, S_COMPARE, S_GOOD, S_BAD); | |
signal CS, ns : STATE_TYPE; | |
begin | |
-- Generate a faster clock for the RAM | |
u0 : Clkgen | |
generic map (BASE_FREQ_G => BASE_FREQ_G, CLK_MUL_G => CLK_MUL_G, CLK_DIV_G => CLK_DIV_G) | |
port map(I => fpgaClk_i, O => sdClk_o); | |
clk <= sdClkFb_i; -- main clock is SDRAM clock fed back into FPGA | |
------------------------------------------------------------------------ | |
-- internal reset flag is set active right after configuration is done | |
-- because the reset counter starts at zero, and then gets reset after | |
-- the counter reaches its upper threshold. | |
------------------------------------------------------------------------ | |
process(clk) | |
constant reset_dly_c : natural := 100; | |
variable rst_cntr : natural range 0 to reset_dly_c := 0; | |
begin | |
if rising_edge(clk) then | |
rst_i <= NO; | |
if rst_cntr < reset_dly_c then | |
rst_i <= YES; | |
rst_cntr := rst_cntr + 1; | |
end if; | |
end if; | |
end process; | |
------------------------------------------------------------------------ | |
-- Instantiate the SDRAM controller that connects the | |
-- module and interfaces to the external SDRAM chip. | |
------------------------------------------------------------------------ | |
u1 : SdramCntl | |
generic map( | |
FREQ_G => FREQ_G, | |
IN_PHASE_G => true, | |
PIPE_EN_G => PIPE_EN_G, | |
MAX_NOP_G => 10000, | |
DATA_WIDTH_G => DATA_WIDTH_G, | |
NROWS_G => NROWS_G, | |
NCOLS_G => NCOLS_G, | |
HADDR_WIDTH_G => HADDR_WIDTH_G, | |
SADDR_WIDTH_G => SADDR_WIDTH_G | |
) | |
port map( | |
clk_i => clk, -- master clock from external clock source (unbuffered) | |
lock_i => YES, -- no DLLs, so frequency is always locked | |
rst_i => rst_i, -- reset | |
rd_i => rd, -- host-side SDRAM read control from memory tester | |
wr_i => wr, -- host-side SDRAM write control from memory tester | |
earlyOpBegun_o => earlyBegun, -- early indicator that memory operation has begun | |
opBegun_o => begun, -- indicates memory read/write has begun | |
rdPending_o => rdPending, -- read operation to SDRAM is in progress_o | |
done_o => done, -- SDRAM memory read/write done indicator | |
rdDone_o => rdDone, -- indicates SDRAM memory read operation is done | |
hostAddr_i => hAddr, -- host-side address from memory tester to SDRAM | |
hostData_i => hDIn, -- test data pattern from memory tester to SDRAM | |
sdramData_o => hDOut, -- SDRAM data output to memory tester | |
status_o => open, -- SDRAM controller state (for diagnostics) | |
sdRas_bo => sdRas_bo, -- SDRAM RAS | |
sdCas_bo => sdCas_bo, -- SDRAM CAS | |
sdWe_bo => sdWe_bo, -- SDRAM write-enable | |
sdBs_o(0) => sdBs_o, -- SDRAM bank address | |
sdAddr_o => sdAddr_o, -- SDRAM address | |
sdData_io => sdData_io -- data to/from SDRAM | |
); | |
process(clk) | |
begin | |
if rising_edge(clk) then | |
if rst_i = '1' then | |
CS <= S_BEGIN; | |
else | |
case CS is | |
when S_BEGIN => | |
chan_io(1) <= '0'; | |
chan_io(3) <= '0'; | |
chan_io(4) <= '0'; | |
chan_io(5) <= '0'; | |
hAddr <= "0"; | |
hDIn <= X"5555"; | |
wr <= '1'; | |
CS <= S_WAIT; | |
when S_WAIT => | |
if (done = '1') then | |
wr <= '0'; | |
CS <= S_READ; | |
end if; | |
when S_READ => | |
-- Light the yellow light if we get this far | |
chan_io(3) <= '1'; | |
hAddr <= "0"; | |
rd <= '1'; | |
CS <= S_READWAIT; | |
when S_READWAIT => | |
if (done = '1') then | |
rd <= '0'; | |
CS <= S_COMPARE; | |
end if; | |
when S_COMPARE => | |
-- Light the blue light if we get this far | |
chan_io(5) <= '1'; | |
if (hDOut = X"5555") then | |
CS <= S_GOOD; | |
else | |
CS <= S_BAD; | |
end if; | |
when S_GOOD => | |
-- Light the green light | |
chan_io(1) <= '1'; | |
when S_BAD => | |
-- Light the red light | |
chan_io(4) <= '1'; | |
end case; | |
end if; | |
end if; | |
end process; | |
end Behavioral; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I used the clk signal for all the processes, including the SDRAM controller, because everything should be clocked off the SDRAM feedback clock so the external SDRAM and the internal FPGA logic stay in sync.
I disabled the SDRAM controller pipelining. You don't need that complexity to start.
I rolled the reset process and the main state machine process together and use just the CS to store the current state.
You also had the roles of hDIn and hDOut reversed: hDIn is the value that is sent into the SDRAM controller which it writes out to the SDRAM; hDOut is the value read from the SDRAM by the controller which is then sent to the host logic in the FPGA.
Try it out and see if it fixes any of your problems.