📄 sdramcntl.vhd
字号:
if refTimer_r /= TO_UNSIGNED(0,refTimer_r'length) then
refTimer_next <= refTimer_r - 1;
else
-- on timeout, reload the timer with the interval between row refreshes
-- and set the flag that indicates a refresh operation is needed.
refTimer_next <= TO_UNSIGNED(REF_CYCLES,refTimer_next'length);
doRfshFlag_next <= YES;
end if;
-- determine if another row or bank in the SDRAM is being addressed
if row /= activeRow_r or bank /= activeBank_r or inactiveFlag_r = YES then
changeRow <= YES;
else
changeRow <= NO;
end if;
-- ***** compute next state and outputs *****
-- SDRAM initialization
if state_r = INITWAIT then
-- initiate wait for SDRAM power-on initialization
-- timer_next <= TO_UNSIGNED(INIT_CYCLES,timer_next'length); -- set timer for init interval
cs_n <= HI;
dqml <= HI;
dqmh <= HI;
initFlag_next <= YES; -- indicate initialization is in progress
if timer_r = TO_UNSIGNED(0,timer_r'length) then
state_next <= INITPCHG; -- precharge SDRAM after power-on initialization
end if;
sdramCntl_state <= "0001";
-- don't do anything if the previous operation has not completed yet.
-- Place this before anything else so operations in the previous state
-- complete before any operations in the new state are executed.
elsif timer_r /= TO_UNSIGNED(0,timer_r'length) then
sdramCntl_state <= "0000";
elsif state_r = INITPCHG then
cmd <= PCHG_CMD; -- initiate precharge of the SDRAM
sAddr(ColCmdPos) <= ALL_BANKS; -- precharge all banks
timer_next <= TO_UNSIGNED(RP_CYCLES,timer_next'length); -- set timer for this operation
-- now setup the counter for the number of refresh ops needed during initialization
rfshCntr_next <= TO_UNSIGNED(RfshCycles,rfshCntr_next'length);
state_next <= INITRFSH; -- perform refresh ops after setting the mode
sdramCntl_state <= "0010";
elsif state_r = INITRFSH then
-- refresh the SDRAM a number of times during initialization
if rfshCntr_r /= TO_UNSIGNED(0,rfshCntr_r'length) then
-- do a refresh operation if the counter is not zero yet
cmd <= RFSH_CMD; -- refresh command goes to SDRAM
timer_next <= TO_UNSIGNED(RFC_CYCLES,timer_next'length); -- refresh operation interval
rfshCntr_next <= rfshCntr_r - 1; -- decrement refresh operation counter
state_next <= INITRFSH; -- return to this state while counter is non-zero
else
-- refresh op counter reaches zero, so set the operating mode of the SDRAM
state_next <= INITSETMODE;
end if;
sdramCntl_state <= "0100";
elsif state_r = INITSETMODE then
-- set the mode register in the SDRAM
cmd <= MODE_CMD; -- initiate loading of mode register in the SDRAM
sAddr <= MODE; -- output mode register bits onto the SDRAM address bits
timer_next <= TO_UNSIGNED(Cmrd,timer_next'length); -- set timer for this operation
state_next <= RW; -- process read/write operations after initialization is done
initFlag_next <= NO; -- reset flag since initialization is done
sdramCntl_state <= "0011";
-- refresh a row of the SDRAM when the refresh timer hits zero and sets the flag
-- and the SDRAM is no longer being initialized or read/written.
-- Place this before the RW state so the host can't block refreshes by doing
-- continuous read/write operations.
elsif doRfshFlag_r = YES and initFlag_r = NO and wrFlag_r = NO and rdFlag_r = NO then
if rasTimer_r = TO_UNSIGNED(0,rasTimer_r'length) and wrTimer_r = TO_UNSIGNED(0,wrTimer_r'length) then
doRfshFlag_next <= NO; -- reset the flag that initiates a refresh operation
cmd <= PCHG_CMD; -- initiate precharge of the SDRAM
sAddr(ColCmdPos) <= ALL_BANKS; -- precharge all banks
timer_next <= TO_UNSIGNED(RP_CYCLES,timer_next'length); -- set timer for this operation
inactiveFlag_next <= YES; -- all rows are inactive after a precharge operation
state_next <= REFRESH; -- refresh the SDRAM after the precharge
end if;
sdramCntl_state <= "0101";
elsif state_r = REFRESH then
cmd <= RFSH_CMD; -- refresh command goes to SDRAM
timer_next <= TO_UNSIGNED(RFC_CYCLES,timer_next'length); -- refresh operation interval
-- after refresh is done, resume writing or reading the SDRAM if in progress
state_next <= RW;
sdramCntl_state <= "0110";
-- do nothing but wait for read or write operations
elsif state_r = RW then
if rd = YES then
-- the host has initiated a read operation
rdFlag_next <= YES; -- set flag to indicate a read operation is in progress
-- if a different row or bank is being read, then precharge the SDRAM and activate the new row
if changeRow = YES then
-- wait for any row activations or writes to finish before doing a precharge
if rasTimer_r = TO_UNSIGNED(0,rasTimer_r'length) and wrTimer_r = TO_UNSIGNED(0,wrTimer_r'length) then
cmd <= PCHG_CMD; -- initiate precharge of the SDRAM
sAddr(ColCmdPos) <= ALL_BANKS; -- precharge all banks
timer_next <= TO_UNSIGNED(RP_CYCLES,timer_next'length); -- set timer for this operation
inactiveFlag_next <= YES; -- all rows are inactive after a precharge operation
state_next <= ACTIVATE; -- activate the new row after the precharge is done
end if;
-- read from the currently active row
else
cmd <= READ_CMD; -- initiate a read of the SDRAM
timer_next <= TO_UNSIGNED(Ccas,timer_next'length); -- setup timer for read access
state_next <= RDDONE; -- read the data from SDRAM after the access time
end if;
sdramCntl_state <= "0111";
elsif wr = YES then
-- the host has initiated a write operation
-- if a different row or bank is being written, then precharge the SDRAM and activate the new row
if changeRow = YES then
wrFlag_next <= YES; -- set flag to indicate a write operation is in progress
-- wait for any row activations or writes to finish before doing a precharge
if rasTimer_r = TO_UNSIGNED(0,rasTimer_r'length) and wrTimer_r = TO_UNSIGNED(0,wrTimer_r'length) then
cmd <= PCHG_CMD; -- initiate precharge of the SDRAM
sAddr(ColCmdPos) <= ALL_BANKS; -- precharge all banks
timer_next <= TO_UNSIGNED(RP_CYCLES,timer_next'length); -- set timer for this operation
inactiveFlag_next <= YES; -- all rows are inactive after a precharge operation
state_next <= ACTIVATE; -- activate the new row after the precharge is done
end if;
-- write to the currently active row
else
cmd <= WRITE_CMD; -- initiate the write operation
dirOut <= YES;
-- set timer so precharge doesn't occur too soon after write operation
wrTimer_next <= TO_UNSIGNED(WR_CYCLES,wrTimer_next'length);
state_next <= WRDONE; -- go back and wait for another read/write operation
end if;
sdramCntl_state <= "1000";
else
null; -- no read or write operation, so do nothing
sdramCntl_state <= "1001";
end if;
-- enter this state when the data read from the SDRAM is available
elsif state_r = RDDONE then
rdFlag_next <= NO; -- set flag to indicate the read operation is over
done <= YES; -- tell the host that the data is ready
state_next <= RW; -- go back and do another read/write operation
sdramCntl_state <= "1010";
-- enter this state when the data is written to the SDRAM
elsif state_r = WRDONE then
dirOut <= YES;
wrFlag_next <= NO; -- set flag to indicate the write operation is over
done <= YES; -- tell the host that the data is ready
state_next <= RW; -- go back and do another read/write operation
sdramCntl_state <= "1011";
-- activate a row of the SDRAM
elsif state_r = ACTIVATE then
cmd <= ACTIVE_CMD; -- initiate the SDRAM activation operation
sAddr <= (others=>'0'); -- output the address for the row that will be activated
sAddr(row'range) <= row;
activeBank_next <= bank; -- remember the active SDRAM row
activeRow_next <= row; -- remember the active SDRAM bank
inactiveFlag_next <= NO; -- the SDRAM is no longer inactive
rasTimer_next <= TO_UNSIGNED(RCD_CYCLES,rasTimer_next'length);
timer_next <= TO_UNSIGNED(RCD_CYCLES,timer_next'length);
state_next <= RW; -- go back and do the read/write operation that caused this activation
sdramCntl_state <= "1100";
-- no operation
else
null;
sdramCntl_state <= "1101";
end if;
end process combinatorial;
-- update registers on the rising clock edge
update: process(clk)
begin
if clk'event and clk='1' then
if rst = NO then
state_r <= INITWAIT;
activeBank_r <= (others=>'0');
activeRow_r <= (others=>'0');
inactiveFlag_r <= YES;
initFlag_r <= YES;
doRfshFlag_r <= NO;
rdFlag_r <= NO;
wrFlag_r <= NO;
rfshCntr_r <= TO_UNSIGNED(0,rfshCntr_r'length);
timer_r <= TO_UNSIGNED(INIT_CYCLES,timer_r'length);
refTimer_r <= TO_UNSIGNED(REF_CYCLES,refTimer_r'length);
rasTimer_r <= TO_UNSIGNED(0,rasTimer_r'length);
wrTimer_r <= TO_UNSIGNED(0,wrTimer_r'length);
else
state_r <= state_next;
activeBank_r <= activeBank_next;
activeRow_r <= activeRow_next;
inactiveFlag_r <= inactiveFlag_next;
initFlag_r <= initFlag_next;
doRfshFlag_r <= doRfshFlag_next;
rdFlag_r <= rdFlag_next;
wrFlag_r <= wrFlag_next;
rfshCntr_r <= rfshCntr_next;
timer_r <= timer_next;
refTimer_r <= refTimer_next;
rasTimer_r <= rasTimer_next;
wrTimer_r <= wrTimer_next;
end if;
end if;
end process update;
end arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -