📄 ddr_sdr.vhd
字号:
variable ps : integer;
begin
ps := +30; -- for synthesis only, values between 0 and +60 are OK for XILINX VirtexII Development Board
-- and CESYS XV2DDR board
-- pragma translate_off
ps := +30; -- for simulation only
-- pragma translate_on
return ps;
end;
begin
rst_int_n <= not srst_sys_q;
sys_rst_qn <= not srst_sys_q;
sys_clk_out <= sys_clk; -- for other modules inside the FPGA
dcm0: entity work.my_dcm generic map (G_CLOCK_FEEDBACK => "1X",
G_CLKIN_PERIOD => "10.0",
G_CLKOUT_PHASE_SHIFT => "FIXED",
G_PHASE_SHIFT => func_phase_shift )
port map ( clkin => clk,
clkfb => clk_fb,
clk0 => clk_int,
clkdv => open,
clk2x => open,
clk90 => open,
clk180 => open,
clk270 => open,
rst => dcm_rst_q,
locked => locked(0)
);
dcm1: entity work.my_dcm generic map (G_CLOCK_FEEDBACK => "1X",
G_CLKIN_PERIOD => "10.0",
G_CLKOUT_PHASE_SHIFT => "FIXED",
G_PHASE_SHIFT => 0 )
port map ( clkin => clk,
clkfb => sys_clk,
clk0 => fpga_clk,
clkdv => open,
clk2x => open,
clk90 => open,
clk180 => open,
clk270 => fpga_clk270,
rst => dcm_rst_q,
locked => locked(1)
);
bufg11: bufg
port map ( o => sys_clk,
i => fpga_clk);
bufg12: bufg
port map ( o => sys_clk270,
i => fpga_clk270);
-------------------------------------------------------
-- User-Interface
-------------------------------------------------------
user_if_inst : user_if
port map (
rst_int_n => rst_int_n,
sys_clk => sys_clk,
cmd => cmd,
addr => addr,
busy_q => busy_q,
cmd_vld => cmd_vld,
init_finished => init_finished_q,
new_cmd_q => new_cmd_q,
new_cmd_ack => new_cmd_ack_q,
do_prech_q => do_prech_q,
do_wait_q => do_wait_q,
cmd_q => cmd_ui_q,
addr_q => addr_ui_q
);
process (sys_clk, rst_int_n) is
variable start_wr : boolean;
variable start_rd : boolean;
begin
if rst_int_n = '0' then
state_q <= IDLE;
sdr_if_q <= COMMAND(NOP);
sdr_if2_q <= COMMAND(NOP);
ld_init_cnt_q <= false;
ct0_q <= false;
ct_cnt_q <= 0;
ld_ct_cnt_q <= false;
ld_dll_cnt_q <= false;
second_refresh_q <= false;
a_int_q <= (others => '0');
a_int2_q <= (others => '0');
cs_int_qn <= '1';
ba_int_q <= (others=>'0');
ba_int2_q <= (others=>'0');
cke_int_q <= '0';
cke_int2_q <= '0';
z_q <= '0';
bus_switch_q <= (others => '0');
rd_ena_q <= false;
wr_ena_q <= '0';
wr_ena2_q <= '0';
wr_ena3_q <= '0';
del_cnt_q <= 0;
del0_q <= true;
ld_del_cnt_q <= false;
w_srg_q <= (others=>'0');
mux_q <= NORMAL;
shift_q(0) <= (others=>'0');
row_adr_q <= (others=>'0');
col_adr_q <= (others=>'0');
tras_cnt_q <= 0;
init_finished_q <= false;
new_cmd_ack_q <= false;
elsif rising_edge(sys_clk) then
-- Default's for variables
start_wr := false;
start_rd := false;
-- default CMD
sdr_if_q <= COMMAND(NOP);
a_int_q <= (others => '0');
cs_int_qn <= '1';
ld_ct_cnt_q <= false;
ld_dll_cnt_q <= false;
ld_init_cnt_q <= false;
init_finished_q <= false;
new_cmd_ack_q <= false;
ld_del_cnt_q <= false;
-- MAIN FSM to generate Controller commands and timing
case state_q is
when IDLE =>
mux_q <= NORMAL;
if locked = "11" then
-- start of ddr-sdram initialization when dcms are locked
assert cke_int_q='0' report "cke_q error!" severity failure;
ld_init_cnt_q <= true;
state_q <= WAIT_200us;
end if;
when WAIT_200us =>
if init_cnt1_q then
cke_int_q <= '1';
end if;
if init_cnt0_q then
ld_ct_cnt_q <= true;
sdr_if_q <= COMMAND(PRECHARGE);
a_int_q(AUTO_PRECHARGE) <= '1'; -- precharge all
state_q <= INIT1_PRECHARGE;
end if;
when INIT1_PRECHARGE =>
if ct0_q then
sdr_if_q <= COMMAND(EXT_MODE);
a_int_q <= EXT_MODE_REG;
ba_int_q <= EXT_MODE_REG_BANK;
ld_ct_cnt_q <= true;
state_q <= INIT_EXT_MODE;
end if;
when INIT_EXT_MODE =>
if ct0_q then
-- set MODE Register
a_int_q <= MODE_REG_DLL_RST;
sdr_if_q <= COMMAND(MODE);
state_q <= INIT1_MODE;
ba_int_q <= BASE_MODE_REG_BANK;
ld_ct_cnt_q <= true;
end if;
when INIT1_MODE =>
if ct0_q then
ld_dll_cnt_q <= true;
state_q <= WAIT_DLL;
end if;
when WAIT_DLL =>
-- wait 200 clk cycles
if dll_cnt0_q then
state_q <= INIT2_PRECHARGE;
sdr_if_q <= COMMAND(PRECHARGE);
ld_ct_cnt_q <= true;
a_int_q(AUTO_PRECHARGE) <= '1'; -- precharge all
end if;
when INIT2_PRECHARGE =>
if ct0_q then
sdr_if_q <= COMMAND(REFRESH);
ld_ct_cnt_q <= true;
state_q <= INIT_REFRESH;
end if;
when INIT_REFRESH =>
if ct0_q then
sdr_if_q <= COMMAND(REFRESH);
ld_ct_cnt_q <= true;
second_refresh_q <= true;
if second_refresh_q then
state_q <= INIT2_MODE;
sdr_if_q <= COMMAND(MODE);
ld_ct_cnt_q <= true;
-- set MODE Reg again (DLL enabled)
a_int_q <= MODE_REG_DLL_ENA;
ba_int_q <= BASE_MODE_REG_BANK;
end if;
end if;
when INIT2_MODE =>
if ct0_q then
state_q <= ST_WAIT_CMD;
init_finished_q <= true;
end if; -- End of Initialization
-- Main State for COMMAND processing ------------------------------------------------------
when ST_WAIT_CMD =>
ba_int_q <= addr_ui_q(addr_ui_q'LEFT-DDR_ADDR_WIDTH downto addr_ui_q'LEFT -DDR_ADDR_WIDTH - (DDR_BANK_WIDTH-1));
-- Store Row and Column address as long as the command is processed
row_adr_q <= addr_ui_q(addr_ui_q'LEFT downto addr_ui_q'LEFT -DDR_ADDR_WIDTH+1);
col_adr_q <= addr_ui_q(addr_ui_q'RIGHT+DDR_ADDR_WIDTH-1 downto 0);
if new_cmd_q then
if do_wait_q and w_srg_q(0)='1'then -- Read2Write or Write2Read
null;
else
-- Acknowledge the command immediately
new_cmd_ack_q <= true;
case cmd_ui_q is
when NOP_CMD =>
null;
when RD_CMD => -- READ -------------------------
mux_q <= NORMAL;
if do_prech_q then
state_q <= RD_PRECH;
else
start_rd := true;
a_int_q <= addr_ui_q(addr_ui_q'RIGHT+DDR_ADDR_WIDTH-1 downto 0) ; -- COL
sdr_if_q <= COMMAND(BURST_RD); -- Kommando setzen
state_q <= ST_READ1;
end if;
when WR_CMD => -- WRITE ------------------------
mux_q <= DELAYED;
if do_prech_q then
state_q <= WR_PRECH;
else
start_wr := true;
-- hier direkt von addr_ui_q laden
a_int_q <= addr_ui_q(addr_ui_q'RIGHT+DDR_ADDR_WIDTH-1 downto 0) ; -- COL
sdr_if_q <= COMMAND(BURST_WR); -- Kommando setzen
state_q <= ST_WRITE1;
end if;
when RFSH_CMD => -- FORCED REFRESH -------------------
mux_q <= NORMAL;
state_q <= ST_RFSH_0;
ld_del_cnt_q <= true; -- wait some clocks before Refresh
when others =>
assert FALSE report "Wrong Command !" severity error;
end case;
end if;
end if;
-- in allen States nach WAIT_CMD die Adresse aus den Registern row_adr und col_adr laden
when ST_WRITE1 =>
state_q <= ST_WAIT_CMD;
when WR_PRECH =>
sdr_if_q <= COMMAND(PRECHARGE);
ld_ct_cnt_q <= true;
state_q <= ST_WR_ACTIVATE;
a_int_q(AUTO_PRECHARGE) <= '1'; -- precharge all
when ST_WR_ACTIVATE =>
if ct_cnt_q=1 then -- Counter direkt abfragen, damit min. Delay erreicht wird
sdr_if_q <= COMMAND(ACTIVE);
a_int_q <= row_adr_q; -- set ROW address
ld_ct_cnt_q <= true;
state_q <= ST_WAIT_WR;
end if;
when ST_WAIT_WR =>
if ct_cnt_q=1 then
start_wr := true;
a_int_q <= col_adr_q; -- set COL address
sdr_if_q <= COMMAND(BURST_WR); -- Kommando setzen
state_q <= ST_WRITE1;
end if;
-- Auto Refresh
-- Do a precharge all, followed by refresh and by an activate for last ROW
when ST_RFSH_0 =>
a_int_q(AUTO_PRECHARGE) <= '1'; -- precharge all, bank-bits are don't care
if del0_q then
-- All banks must be precharged before Refresh
sdr_if_q <= COMMAND(PRECHARGE);
ld_ct_cnt_q <= true;
state_q <= ST_RFSH_1;
end if;
when ST_RFSH_1 =>
if ct_cnt_q=1 then
state_q <= ST_RFSH_2;
sdr_if_q <= COMMAND(REFRESH);
ld_ct_cnt_q <= true;
end if;
when ST_RFSH_2 =>
if ct_cnt_q=1 then
ld_ct_cnt_q <= true;
a_int_q <= row_adr_q; -- set current ROW address
sdr_if_q <= COMMAND(ACTIVE);
-- Active to RD/WR or Active to Precharge?
if do_prech_q then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -