我必须为VHDL中的课程开发一个SDRAM控制器。但这是我第一次使用VHDL,它具有非常重要的学习曲线。
我已经从github(https://github.com/christianmiyoshi/SDRAM_Controller_VHDL/blob/master/sdram_controller.vhd)下载了一个SDRAM控制器,我正在尝试完成它。
我试图在地址中写入数据,然后再读取,但我无法读取单个数据。我不知道我的问题是在写作还是在阅读过程中。
有人可以帮助我吗?
谢谢大家!
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ram_controller is
port(
clk : in std_logic;
reset: in std_logic;
refresh: in std_logic;
read_write_enable: in std_logic;
write_n: in std_logic;
address: in std_logic_vector(21 downto 0);
data_in: in std_logic_vector(15 downto 0);
dqmu: in std_logic;
dqml: in std_logic;
ready: out std_logic;
done: out std_logic;
data_out: out std_logic_vector(15 downto 0);
single_burst: in std_logic; --0 single y 1 burst
SDRAM_CKE: out std_logic;
SDRAM_CS_N: out std_logic;
SDRAM_RAS_N: out std_logic;
SDRAM_CAS_N: out std_logic;
SDRAM_WE_N: out std_logic;
SDRAM_BA: out std_logic_vector(1 downto 0);
SDRAM_SA: out std_logic_vector(11 downto 0);
SDRAM_DQ: inout std_logic_vector(15 downto 0);
SDRAM_DQM: out std_logic_vector(1 downto 0)
);
end entity;
architecture behavior of ram_controller is
type state_type is (init_ckeLow,init_stableclock,init_wait,init_nopCommand,init_prechargeAll,init_refresh_1,init_mode,init_refresh_2,idle,refresh_state,activate_row,activate_rcd,read_write,ras1,ras2,precharge);
signal state: state_type := init_ckeLow;
signal ticks: std_logic_vector(7 downto 0) := (others => '0');
signal ticks_ref: integer := 0;
signal ticks_ref_refresh: integer := 0;
constant burstMode: std_logic := '0';
constant casLatency: std_logic_vector(2 downto 0) := "010";
constant burstType: std_logic := '0';
constant burstLength: std_logic_vector(2 downto 0) := "000";
--signal highz_output: std_logic:= '0';
constant MODE_REG: std_logic_vector(11 downto 0) := "00" & burstMode & "00" & casLatency & burstType & burstLength;
constant MODE_REG_BURST: std_logic_vector(11 downto 0) := "000000100111";
signal command: std_logic_vector(3 downto 0);
signal row: std_logic_vector(11 downto 0);
signal column: std_logic_vector(7 downto 0);
signal bank: std_logic_vector(1 downto 0);
signal sd_busdir_x: std_logic:='0';
-- Command truth table
-- CS_N,RAS_N,CAS_N,WE_N
constant CMD_actIVATE: std_logic_vector(3 downto 0) := "0011";
constant CMD_PRECHARGE: std_logic_vector(3 downto 0) := "0010";
constant CMD_WRITE: std_logic_vector(3 downto 0) := "0100";
constant CMD_READ: std_logic_vector(3 downto 0) := "0101";
constant CMD_MODE: std_logic_vector(3 downto 0) := "0000";
constant CMD_NOP: std_logic_vector(3 downto 0) := "0111";
constant CMD_REFRESH: std_logic_vector(3 downto 0) := "0001";
signal address_buffer: std_logic_vector(21 downto 0) := (others => '0');
signal data_in_buffer: std_logic_vector(15 downto 0) := (others => '0');
signal dqu_buffer: std_logic := '0';
signal dql_buffer: std_logic := '0';
signal ready_buffer: std_logic := '0';
signal done_buffer: std_logic := '0';
signal data_out_buffer: std_logic_vector(15 downto 0) := (others => '0');
signal CKE: std_logic;
signal CS_N: std_logic;
signal RAS_N: std_logic;
signal CAS_N: std_logic;
signal WE_N: std_logic;
signal BA: std_logic_vector(1 downto 0);
signal SA: std_logic_vector(11 downto 0);
signal DQ: std_logic_vector(15 downto 0);
signal DQM: std_logic_vector(1 downto 0);
signal contador : std_logic_vector(15 downto 0) := x"0000";
signal modo: std_logic := '0';
begin
(CS_N,WE_N) <= command;
SDRAM_CKE <= CKE;
SDRAM_CS_N <= CS_N;
SDRAM_RAS_N <= RAS_N;
SDRAM_CAS_N <= CAS_N;
SDRAM_WE_N <= WE_N;
SDRAM_BA <= BA;
SDRAM_SA <= SA;
--SDRAM_DQ <= DQ;
SDRAM_DQM <= DQM;
--SA <= address_buffer;
SDRAM_DQ <= data_in_buffer when sd_busdir_x = '1' else (others => 'Z');
DQM <= dqu_buffer & dql_buffer;
ready <= ready_buffer;
done <= done_buffer;
data_out <= data_out_buffer;
bank <= address(21 downto 20);
row <= address(19 downto 8);
column <= address(7 downto 0);
process(clk,reset)
begin
if reset = '0' then
state <= init_ckeLow;
ticks_ref <= 0;
elsif rising_edge(clk) then
if ticks_ref /= 0 then
ticks_ref <= ticks_ref - 1;
else
-- micron datasheet instructions
-- Frequency = 100 Mhz => period of 10ns
-- 1: Apply Vdd and Vddq simultaneously
case state is
when init_ckeLow =>
-- 2: Assert and hold CKE ant LVTTL logic low
ticks_ref <= 10;
CKE <= '0';
state <= init_stableclock;
when init_stableclock =>
-- 3: Provide stable clock
ticks_ref <= 10;
state <= init_wait;
when init_wait=>
-- 4: Wait at least 100us
-- 5: bring cke high at some point of the period
-- with command inhibit or nop
--ticks_ref <= 10000;
ticks_ref <= 2; -- debugadd
state <= init_nopCommand;
when init_nopCommand =>
--ticks_ref <= 10000;
ticks_ref <= 2; -- debug
CKE <= '1';
command <= CMD_NOP;
state <= init_prechargeAll;
when init_prechargeAll =>
-- 6: perform precharge all
-- 7: wait at leas t_RP
command <= CMD_PRECHARGE;
BA <= "00";
SA(10) <= '1'; -- all banks
ticks_ref <= 2;
ticks_ref_refresh <= 8;
state <= init_refresh_1;
when init_refresh_1 =>
-- auto refresj period: < 64 ns
if ticks_ref_refresh = 0 then
state <= init_mode;
else
ticks_ref_refresh <= ticks_ref_refresh - 1;
command <= CMD_REFRESH;
ticks_ref <= 7;
end if;
when init_mode =>
command <= CMD_MODE;
if single_burst = '0' then
SA <= MODE_REG;
modo <= '0';
else
SA <= MODE_REG_BURST;
modo <= '1';
end if;
BA <= "00";
ticks_ref <= 2;
ticks_ref_refresh <= 8;
state <= init_refresh_2;
when init_refresh_2 =>
if ticks_ref_refresh = 0 then
state <= idle;
--done_buffer <= '1';
else
ticks_ref_refresh <= ticks_ref_refresh - 1;
command <= CMD_REFRESH;
ticks_ref <= 7;
end if;
when idle =>
done_buffer <= '0';
contador <= (others => '0');
if read_write_enable = '1' then
-- tras: active to precharge: 45 ns min,120000ns max
state <= activate_row;
command <= CMD_actIVATE;
SA <= row;
BA <= bank;
--done_buffer <= '0';
elsif refresh = '1' then
state <= refresh_state;
command <= CMD_REFRESH;
ticks_ref <= 7;
--done_buffer <= '0';
end if;
when refresh_state =>
state <= idle;
--done_buffer <= '1';
when activate_row =>
--trcd 20 ns
command <= CMD_NOP;
state <= activate_rcd;
data_in_buffer <= data_in;
ticks_ref <= 1;
when activate_rcd =>
-- trcs = 20ns min
state <=read_write;
SA <= "0000" & column;
if write_n = '0' then
command <= CMD_WRITE;
dqu_buffer <= dqmu;
dql_buffer <= dqml;
sd_busdir_x <= '1';
else
command <= CMD_READ;
end if;
when read_write =>
--command <= CMD_NOP;
state <= ras1;
--if modo='0' then
--sd_busdir_x <= '0';
--end if;
when ras1 =>
state <= ras2;
command <= CMD_NOP;
when ras2 =>
-- trp = 20ns min
if modo='1' and contador <= x"00FF" then
data_in_buffer <= data_in;
state <= ras2;
contador <= contador +1;
else
contador <= (others => '0');
state <= precharge;
sd_busdir_x <= '0';
command <= CMD_PRECHARGE;
SA(10) <= '1';
data_out_buffer <= SDRAM_DQ;
ticks_ref <= 2;
end if;
when precharge =>
state <= idle;
done_buffer <= '1';
ticks_ref <= 1;
end case;
end if;
end if;
end process;
end architecture;
[enter image description here][1]
[1]: https://i.stack.imgur.com/CaqqL.png