📄 command_statemachine.vhd
字号:
-- otherwise wait for Tras to expire
--elsif Tras_end = '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;
end if; -- if bus2ip_rdreq
end if; -- if refresh
else
Tcmd_load <= '0';
Tcmd_cnt_en <= '1';
end if; -- if tcmd_end
-------------------------- WRITE_CMD --------------------------
when WRITE_CMD =>
-- assert ToutSup
ToutSup <= '1';
-- if doing a write, disable the input DQS registers
read_dqs_ce_i <= '0';
-- keep the counters enabled
--write_state_cmb <= '1';
GPcnt_en <= '1';
dq_oe_cmb_i <= '0'; -- assert output enable
dqs_oe_cmb <= '0';
dq_ecc_oe_cmb_i <= '0';
dqs_ecc_oe_cmb <= '0';
-- prepare for WRITE_DATA state
-- when command timer ends, see if this is a burst
-- so that a new command can be issued
-- If there is a need for a refresh command, (Trefi_end=1)
-- don't service the burst
if Tcmd_end = '1' then
if Trefi_end = '1' then
-- refresh command
-- must first wait for Twr to expire and then issue
-- PRECHARGE
if Twr_end = '1' then
-- data transmission is done
-- if Tras has expired, go to PRECHARGE,
-- otherwise wait for Tras to expire
dq_oe_cmb_i <= '1'; -- negate output enable
dqs_oe_cmb <= '1';
dq_ecc_oe_cmb_i <= '1';
dqs_ecc_oe_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
cmdsm_ns <= WAIT_TWR;
end if; -- if twr_end
elsif Bus2IP_WrReq = '1' then
-- write burst
if Same_row = '1' then
-- access is to the same row, issue write command
RCW_cmd <= WRITE_RCW;
DDR_Addr <= Col_addr;
DDR_BankAddr <= Bank_addr;
cmdsm_ns <= WRITE_CMD;
Tcmd_load <= '1';
Tcmd_cnt_en <= '0';
Wr_AddrAck <= '1';
pend_write_cmb <= '1';
else
pend_write_cmb <= '0';
-- access is to a different row
-- if same bank, have to PRECHARGE
if Same_bank = '1' then
if Twr_end = '1' then
-- data transmission is done
-- if Tras has expired, go to PRECHARGE,
-- otherwise wait for Tras to expire
dq_oe_cmb_i <= '1'; -- negate output enable
dqs_oe_cmb <= '1';
dq_ecc_oe_cmb_i <= '1';
dqs_ecc_oe_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
cmdsm_ns <= WAIT_TWR;
end if; -- if twr_end
else
-- different bank, can go to ACTIVE
-- if Trrd has expired, prepare for ACTIVE cmd, else
-- wait for Trrd to expire
if Twr_end = '1' then
-- data transmission is done
-- if Tras has expired, go to PRECHARGE,
-- otherwise wait for Tras to expire
dq_oe_cmb_i <= '1'; -- negate output enable
dqs_oe_cmb <= '1';
dq_ecc_oe_cmb_i <= '1';
dqs_ecc_oe_cmb <= '1';
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';
cmdsm_ns <= ACT_CMD;
else
cmdsm_ns <= WAIT_TRRD;
end if; -- if trrd_end
else
cmdsm_ns <= WAIT_TWR;
end if; -- if twr_end
end if; -- if same_bank
end if; -- if same_row
else
pend_write_cmb <= '0';
if Twr_end = '1' then
-- data transmission is done
-- if Tras has expired, go to PRECHARGE,
-- otherwise wait for Tras and Twr to expire
dq_oe_cmb_i <= '1'; -- negate output enable
dqs_oe_cmb <= '1';
dq_ecc_oe_cmb_i <= '1';
dqs_ecc_oe_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
cmdsm_ns <= WAIT_TWR;
end if; -- if twr_end
end if; -- if bus2ip_wrreq
else
pend_write_cmb <= '0';
Tcmd_load <= '0';
Tcmd_cnt_en <= '1';
end if; --tcmd_end
---------------------------- WAIT_TWR --------------------------
when WAIT_TWR =>
-- assert ToutSup
ToutSup <= '1';
-- wait in this state for the write recovery and TRAS
dq_oe_cmb_i <= '1';
dqs_oe_cmb <= '1';
dq_ecc_oe_cmb_i <= '1';
dqs_ecc_oe_cmb <= '1';
if Tras_end = '1' and Twr_end = '1' then
cmdsm_ns <= PRECHARGE_CMD;
RCW_cmd <= PRECHARGE_RCW;
DDR_Addr <= PRECHARGE_DATA;
GPcnt_load <= '1';
GPcnt_data <= C_RPCNT;
end if;
-------------------------- PRECHARGE_CMD --------------------------
when PRECHARGE_CMD =>
-- keep the general purpose counter enable to count Trp
-- keep the Trc counter enabled
Twr_rst <= '1';
GPcnt_en <= '1';
if Trefi_end = '1' or read_state = '0' or Bus2IP_RdReq = '1' then
-- either refresh or initialization or write xfer
-- or an interrupted read burst
-- assert ToutSup
-- ToutSup is not asserted if waiting for read_data_done
ToutSup <= '1';
end if;
-- go to IDLE state once Trp and Trc have expired
-- Note: if came to this state to do a REFRESH, Trefi_end will
-- still be asserted, so will get to REFRESH state through IDLE
if GPcnt_end = '1' and Trc_end = '1' then
if read_state = '0' then
-- either refresh or initialization or write xfer
-- go to IDLE
cmd_done_cmb <= '1';
cmdsm_ns <= IDLE;
else
-- end of read transaction or interrupted read, must wait for Read_data_done
if Read_data_done = '1' then
cmd_done_cmb <= '1';
read_data_done_rst_cmb <= '1';
cmdsm_ns <= IDLE;
end if;
end if;
end if;
-- Remove Retry assertion during RdAcks on OPB bus
if Trefi_end='1' and C_PLB_BUS = 1 then
-- refresh
-- assert Retry
Retry <= '1';
end if;
-------------------------- WAIT_TRAS --------------------------
when WAIT_TRAS =>
-- assert ToutSup
ToutSup <= '1';
-- go to PRECHARGE_CMD state once Tras has expired
-- if write transaction, also insure that Twr has expired
if Trefi_end='1' then
-- refresh
-- assert Retry
Retry <= '1';
end if;
if Tras_end = '1' then
cmdsm_ns <= PRECHARGE_CMD;
RCW_cmd <= PRECHARGE_RCW;
DDR_Addr <= PRECHARGE_DATA;
GPcnt_load <= '1';
GPcnt_data <= C_RPCNT;
end if;
-------------------------- WAIT_TRRD --------------------------
when WAIT_TRRD =>
-- assert ToutSup
ToutSup <= '1';
-- go to ACT_CMD state once Trrd has expired
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';
cmdsm_ns <= ACT_CMD;
end if;
---------------------------- DEFAULT --------------------------
when others =>
cmd_done_cmb <= '1';
cmdsm_ns <= IDLE;
end case;
end process CMDSM_CMB;
-- Note: most outputs from this state machine will be registered in the I/O module
-- and are not registered here
CMDSM_REG: process (Clk)
begin
if (Clk'event and Clk = '1') then
if (Rst = RESET_ACTIVE) then
cmdsm_cs <= IDLE;
Cmd_done <= '0';
pend_write_reg <= '0';
read_state <= '0';
Read_dqs_ce <= '1';
Read_data_done_rst <= '1';
csn_cmd_reg <= (others => '1');
else
cmdsm_cs <= cmdsm_ns;
Read_dqs_ce <= read_dqs_ce_i;
if rst_read_state = '1' then
read_state <= '0';
else
read_state <= read_state_cmb;
end if;
Cmd_done <= cmd_done_cmb;
pend_write_reg <= pend_write_cmb;
Read_data_done_rst <= read_data_done_rst_cmb;
-- Duplicate registered output logic in IOB for DDR_CSn
csn_cmd_reg <= csn_cmd;
end if;
end if;
end process CMDSM_REG;
Reset_pendwrreq <= reset_pendwrreq_cmb;
Reset_pendrdreq <= reset_pendrdreq_cmb;
-- Seperate sequential process for read_pause based on C_INCLUDE_BURSTS parameter
W_BURST: if C_INCLUDE_BURSTS = 1 generate
READ_PAUSE_REG: process (Clk)
begin
if (Clk'event and Clk = '1') then
if (Rst = RESET_ACTIVE) then
read_pause_i <= '0';
else
-- Add Bus2IP_CS to reset condition
if Read_data_done = '1' or Comb_Bus2IP_CS = '0' then
read_pause_i <= '0';
else
read_pause_i <= read_pause_cmb;
end if;
end if;
end if;
end process READ_PAUSE_REG;
end generate W_BURST;
WO_BURST: if C_INCLUDE_BURSTS = 0 generate
read_pause_i <= '0';
end generate WO_BURST;
end imp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -