📄 command_statemachine.vhd
字号:
Trefi_load <= '0';
Trc_load <= '0';
Trrd_load <= '0';
Tras_load <= '0';
GPcnt_en <= '0';
GPcnt_load <= '0';
GPcnt_data <= (others => '1');
cmdsm_ns <= cmdsm_cs;
Retry <= '0';
reset_pendrdreq_cmb <= '0';
reset_pendwrreq_cmb <= '0';
dq_oe_cmb_i <= '1';
dq_ecc_oe_cmb_i <= '1';
dqs_oe_cmb <= '1';
dqs_ecc_oe_cmb <= '1';
dqs_setrst_cmb <= '0';
dqs_ecc_setrst_cmb <= '0';
dqs_rst_cmb <= '0';
dqs_ecc_rst_cmb <= '0';
rst_read_state <= '0';
read_state_cmb <= read_state;
Rd_AddrAck <= '0';
Wr_AddrAck <= '0';
Twr_rst <= '0';
read_data_done_rst_cmb <= '0';
ToutSup <= '0';
read_pause_cmb <= read_pause_i;
read_dqs_ce_i <= '1';
case cmdsm_cs is
-------------------------- IDLE --------------------------
when IDLE =>
-- reset state
Twr_rst <= '1';
rst_read_state <= '1';
-- while in IDLE, drive the DQS lines to the pullup/pulldown value
dqs_oe_cmb <= '1';
dqs_ecc_oe_cmb <= '1';
dqs_setrst_cmb <= '1';
dqs_ecc_setrst_cmb <= '1';
-- setup the command so that once its registered,
-- it'll line up with the state
if Refresh='1' or
(init_done = '1' and Trefi_end='1') then
cmdsm_ns <= REFRESH_CMD;
RCW_cmd <= REFRESH_RCW;
csn_cmd <= (others => '0'); -- Assert CS of all memory banks during refresh
-- reload the refresh interval timer
Trefi_load <= '1';
-- load the general purpose counter to time refresh
-- command to another command delay
GPcnt_load <= '1';
GPcnt_data <= C_RFCCNT;
-- assert Retry
Retry <= '1';
elsif Comb_Bus2IP_CS = '1' and Init_done = '1' then
-- prepare for ACTIVE command
cmdsm_ns <= ACT_CMD;
RCW_cmd <= ACTIVE_RCW;
csn_cmd <= not (Bus2IP_CS);
DDR_Addr <= Row_addr;
DDR_BankAddr <= Bank_addr;
-- load the general purpose counter to time Trcd
GPcnt_load <= '1';
GPcnt_data <= C_RCDCNT;
-- load the RAS counter to time Tras
Tras_load <= '1';
-- load the RRD counter to time Trrd
Trrd_load <= '1';
-- load the RC counter to time Trc
Trc_load <= '1';
elsif Load_mr = '1' then
cmdsm_ns <= LOAD_MR_CMD;
RCW_cmd <= LOAD_MR_RCW;
csn_cmd <= (others => '0'); -- Assert all CS during load mode register
DDR_Addr <= Register_data;
DDR_BankAddr <= Register_sel;
GPcnt_load <= '1';
GPcnt_data <= C_MRDCNT;
elsif Precharge = '1' then
cmdsm_ns <= PRECHARGE_CMD;
RCW_cmd <= PRECHARGE_RCW;
if (init_done = '0') then
csn_cmd <= (others => '0'); -- Precharge all banks during initialization
else csn_cmd <= not (Bus2IP_CS); -- Else precharge specific memory bank
end if;
DDR_Addr <= PRECHARGE_DATA;
GPcnt_load <= '1';
GPcnt_data <= C_RPCNT;
end if;
-------------------------- REFRESH_CMD --------------------------
when REFRESH_CMD =>
-- start timing refresh command cycle.
GPcnt_en <= '1';
-- assert Retry
Retry <= '1';
-- assert ToutSup
ToutSup <= '1';
if C_OPB_BUS = 1 then
-- When timer expires
-- return to IDLE state if write transaction
-- because write buffer is controlling Bus2IP_CS
-- if read, must wait for Bus2IP_CS to negate so that the bus
-- has reacted to the retry
if GPcnt_end = '1' then
if read_state= '1' or Bus2IP_RdReq = '1' then
if Comb_Bus2IP_CS = '0' then
cmd_done_cmb <= '1';
cmdsm_ns <= IDLE;
end if;
else
cmd_done_cmb <= '1';
cmdsm_ns <= IDLE;
end if;
end if;
end if;
if C_PLB_BUS = 1 then
-- when timer expires, return to IDLE state if CS is negated
-- Data phase can't abort on PLB, so if CS is still valid
-- go to ACT state
if GPcnt_end = '1'then
cmd_done_cmb <= '1';
if Comb_Bus2IP_CS = '1' then
cmdsm_ns <= ACT_CMD;
RCW_cmd <= ACTIVE_RCW;
csn_cmd <= not (Bus2IP_CS); -- Assert CS of active memory bank
DDR_Addr <= Row_addr;
DDR_BankAddr <= Bank_addr;
-- load the general purpose counter to time Trcd
GPcnt_load <= '1';
GPcnt_data <= C_RCDCNT;
-- load the RAS counter to time Tras
Tras_load <= '1';
-- load the RRD counter to time Trrd
Trrd_load <= '1';
-- load the RC counter to time Trc
Trc_load <= '1';
else
cmdsm_ns <= IDLE;
end if;
end if;
end if;
-------------------------- LOAD_MR_CMD --------------------------
when LOAD_MR_CMD =>
-- assert the count enable to start timing LOAD_MR command
-- cycle.
GPcnt_en <= '1';
Retry <= '1';
-- assert ToutSup
ToutSup <= '1';
if C_OPB_BUS = 1 then
-- When timer expires and Comb_Bus2IP_CS=0,
-- return to IDLE state
-- must wait for Comb_Bus2IP_CS to negate so that the bus
-- has reacted to the retry
if GPcnt_end = '1' and Comb_Bus2IP_CS = '0' then
cmd_done_cmb <= '1';
cmdsm_ns <= IDLE;
end if;
end if;
if C_PLB_BUS = 1 then
-- when timer expires, return to IDLE state
-- Data phase can't abort on PLB, so CS is still valid
if GPcnt_end = '1'then
cmd_done_cmb <= '1';
cmdsm_ns <= IDLE;
end if;
end if;
-------------------------- ACT_CMD --------------------------
when ACT_CMD =>
-- assert general purpose counter enable to start timing Trcd
GPcnt_en <= '1';
-- assert reset to DQS registers to insure 1 clock of DQS=0
-- DQS output enable will only output this if write cycle
dqs_rst_cmb <= '1';
dqs_ecc_rst_cmb <= '1';
-- assert ToutSup
ToutSup <= '1';
if Trefi_end='1' then
-- refresh, assert Retry
Retry <= '1';
-- must go to to precharge to close row
if Tras_end = '1' then
cmdsm_ns <= PRECHARGE_CMD;
RCW_cmd <= PRECHARGE_RCW;
DDR_Addr <= PRECHARGE_DATA;
GPcnt_load <= '1';
GPcnt_data <= C_RPCNT;
else
cmdsm_ns <= WAIT_TRAS;
end if;
elsif Comb_Bus2IP_CS = '0' then
-- CS has negated (master abort)
-- must go to to precharge to close row
if Tras_end = '1' then
cmdsm_ns <= PRECHARGE_CMD;
RCW_cmd <= PRECHARGE_RCW;
DDR_Addr <= PRECHARGE_DATA;
GPcnt_load <= '1';
GPcnt_data <= C_RPCNT;
else
cmdsm_ns <= WAIT_TRAS;
end if;
elsif GPcnt_end = '1' then
-- Trcd is complete
-- load the command counter
Tcmd_load <= '1';
if read_state = '1' then
-- need to continue an interrupted read transaction
-- wait for data to be completed
if read_data_done = '1' then
-- prepare for READ_CMD state
RCW_cmd <= READ_RCW;
DDR_Addr <= Col_addr;
DDR_BankAddr <= bank_addr;
cmdsm_ns <= READ_CMD;
pend_read_cmb <= '1';
reset_pendrdreq_cmb <= '1';
Rd_addrAck <= '1';
-- release read data done reset
read_data_done_rst_cmb <= '1';
end if;
elsif Pend_rdreq ='1' or Bus2IP_RdReq = '1' then
-- prepare for READ_CMD state
RCW_cmd <= READ_RCW;
DDR_Addr <= Col_addr;
DDR_BankAddr <= bank_addr;
cmdsm_ns <= READ_CMD;
pend_read_cmb <= '1';
reset_pendrdreq_cmb <= '1';
Rd_addrAck <= '1';
elsif Pend_wrreq = '1' or Bus2IP_WrReq = '1'then
-- check for new write request or if need to finish write burst
-- prepare for WRITE_CMD state
RCW_cmd <= WRITE_RCW;
DDR_Addr <= Col_addr;
DDR_BankAddr <= bank_addr;
cmdsm_ns <= WRITE_CMD;
pend_write_cmb <= '1';
reset_pendwrreq_cmb <= '1';
Wr_addrAck <= '1'; -- start IPIC address counters
dq_oe_cmb_i <= '0'; -- assert output enable
dqs_oe_cmb <= '0';
dq_ecc_oe_cmb_i <= '0';
dqs_ecc_oe_cmb <= '0';
end if;
end if;
-------------------------- READ_CMD --------------------------
when READ_CMD =>
-- when command timer ends, see if this is a burst
-- so that a new command can be issued
read_state_cmb <= '1';
-- assert ToutSup
ToutSup <= '1';
if Tcmd_end = '1' then
if Trefi_end = '1' then
-- go handle refresh
-- have to PRECHARGE
-- assert read_pause
read_pause_cmb <= '1';
if Tras_end = '1' then
cmdsm_ns <= PRECHARGE_CMD;
RCW_cmd <= PRECHARGE_RCW;
DDR_Addr <= PRECHARGE_DATA;
GPcnt_load <= '1';
GPcnt_data <= C_RPCNT;
else
cmdsm_ns <= WAIT_TRAS;
end if;
else
if Bus2IP_RdReq = '1' then
if Same_row = '1' then
-- access is to the same row, can repeat read command
RCW_cmd <= READ_RCW;
DDR_Addr <= Col_addr;
DDR_BankAddr <= bank_addr;
cmdsm_ns <= READ_CMD;
Tcmd_load <= '1';
Tcmd_cnt_en <= '0';
pend_read_cmb <= '1';
Rd_addrAck <= '1';
else
-- access is to a different row
-- if same bank, have to precharge
-- assert read_pause
read_pause_cmb <= '1';
if Same_bank = '1' then
if Tras_end = '1' then
cmdsm_ns <= PRECHARGE_CMD;
RCW_cmd <= PRECHARGE_RCW;
DDR_Addr <= PRECHARGE_DATA;
GPcnt_load <= '1';
GPcnt_data <= C_RPCNT;
else
cmdsm_ns <= WAIT_TRAS;
end if;
else
-- different bank - can go to ACTIVE
-- if Trrd has expired, prepare for ACTIVE cmd, else
-- wait for Trrd to expire
if Trrd_end = '1' then
RCW_cmd <= ACTIVE_RCW;
csn_cmd <= not (Bus2IP_CS); -- Assert CS of active memory bank
DDR_Addr <= Row_addr;
DDR_BankAddr <= Bank_addr;
-- load the general purpose counter to time Trcd
GPcnt_load <= '1';
GPcnt_data <= C_RCDCNT;
-- load the RAS counter to time Tras
Tras_load <= '1';
-- load the RC counter to time Trc
Trc_load <= '1';
-- reset read_data_done
read_data_done_rst_cmb <= '1';
cmdsm_ns <= ACT_CMD;
else
cmdsm_ns <= WAIT_TRRD;
end if;
end if;
end if; -- if same bank, different row
else
-- not a burst
-- if Tras has expired, go to PRECHARGE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -