📄 pctosraminterface-sv06.vhd
字号:
elsif syncWrite = '0' and syncRead = '0' then
nextState <= stGetSettings1;
end if;
end if;
stateOutput <= "0001";
when stGetAddr1 =>
nextState <= stGetAddr1;
case inSliceNum is
when "00" =>
when "01" =>
-- syncNextSlice should be high.
-- We wait for syncNextSlice to go low:
if syncNextSlice = '0' then
-- Read the next address slice and
-- increment the input slice number:
regCurAddr <= '1';
incInSliceNum <= '1';
end if;
when "10" =>
-- syncNextSlice should be low.
-- We wait for syncNextSlice to go high:
if syncNextSlice = '1' then
regCurAddr <= '1';
incInSliceNum <= '1';
end if;
when others =>
-- inSliceNum should be "11" here.
-- syncNextSlice should be high.
-- We wait for syncNextSlice to go low:
-- We are waiting for the final slice:
if (syncNextSlice = '0' and syncWrite = '0' and
syncRead = '0') then
-- After this we are done setting
-- the address.
nextState <= stIdle;
regCurAddr <= '1';
clearInSliceNum <= '1';
end if;
end case;
-- The only exception to the above is that if
-- syncWrite or syncRead have been prematurely changed
-- then we abort the current operation.
if inSliceNum /= "11" and
(syncWrite = '0'or syncRead = '0') then
nextState <= stIdle;
clearInSliceNum <= '1';
end if;
when stDoWrite1 =>
nextState <= stDoWrite1;
case inSliceNum is
when "00" =>
when "01" =>
-- syncNextSlice should be high.
-- We wait for syncNextSlice to go low:
if syncNextSlice = '0' then
-- Read the next write data slice and
-- increment the input slice number:
regWriteData <= '1';
incInSliceNum <= '1';
end if;
when "10" =>
-- syncNextSlice should be low.
-- We wait for syncNextSlice to go high:
if syncNextSlice = '1' then
regWriteData <= '1';
incInSliceNum <= '1';
end if;
when others =>
-- inSliceNum should be "11" here.
-- syncNextSlice should be high.
-- We wait for syncNextSlice to go low:
-- We are waiting for the final slice:
if (syncNextSlice = '0' and syncWrite = '0') then
-- We are reading the final slice,
-- so after this we actually perform
-- the write to SRAM:
nextState <= stDoWrite2;
regWriteData <= '1';
clearInSliceNum <= '1';
end if;
end case;
-- The only exception to the above is that if
-- syncWrite has been prematurely changed
-- then we abort the current operation.
if (inSliceNum /= "11" and syncWrite = '0') then
nextState <= stIdle;
clearInSliceNum <= '1';
end if;
when stDoWrite2 =>
nextState <= stDoWrite2;
-- Wait to request the actual write to SRAM:
if canWrite = '1' then
-- The write will take place in subsequent
-- clock cycle(s). We don't need to wait for
-- the write to finish, since this FSM runs
-- much faster than the rate at which the PC
-- can control the parallel port.
nextState <= stIdle;
doSRAMWrite <= '1';
-- Auto-increment the current address:
incCurAddr <= '1';
end if;
when stDoRead1 =>
nextState <= stDoRead1;
-- Wait to request the actual read from SRAM:
if canRead = '1' then
nextState <= stDoRead2;
doSRAMRead <= '1';
end if;
when stDoRead2 =>
nextState <= stDoRead2;
-- Wait for the read to complete:
if canRead = '1' then
nextState <= stDoRead3;
-- readData will be valid at the end of this
-- clock cycle, so we register it at that point:
regReadData <= '1';
-- Clear outSliceNum so that the first slice
-- we output for the PC will be slice 0.
clearOutSliceNum <= '1';
end if;
when stDoRead3 =>
nextState <= stDoRead3;
case outSliceNum is
when "00" =>
-- syncNextSlice should be high.
-- We wait for syncNextSlice to go low:
if syncNextSlice = '0' then
-- Increment the output slice number
-- to output the next read data slice
-- to the PC:
incOutSliceNum <= '1';
end if;
when "01" =>
-- syncNextSlice should be low.
-- We wait for syncNextSlice to go high:
if syncNextSlice = '1' then
incOutSliceNum <= '1';
end if;
when "10" =>
-- syncNextSlice should be high.
-- We wait for syncNextSlice to go low:
-- We are waiting to output the final slice:
if (syncNextSlice = '0' and syncRead = '0') then
-- After this we have finished
-- performing the read:
nextState <= stIdle;
-- Auto-increment the current address:
incCurAddr <= '1';
-- Increment the output slice number
-- to output the final read data slice
-- to the PC:
incOutSliceNum <= '1';
end if;
when others =>
end case;
-- The only exception to the above is that if
-- syncRead has been prematurely changed
-- then we abort the current operation.
-- Note that for reads, outSliceNum is compared
-- with the value "10" in the line below, rather
-- than "11" that we compare inSliceNum with
-- when doing address setting and writes.
if (outSliceNum /= "10" and syncRead = '0') then
nextState <= stIdle;
end if;
when stGetSettings1 =>
nextState <= stGetSettings1;
if (syncNextSlice = '0' and syncWrite = '0'
and syncRead = '0') then
nextState <= stGetSettings2;
elsif not (syncNextSlice = '1' and syncWrite = '0'
and syncRead = '0') then
nextState <= stIdle;
end if;
-- Debug:
stateOutput <= "1000";
when stGetSettings2 =>
nextState <= stGetSettings2;
if (syncNextSlice = '0' and syncWrite = '1'
and syncRead = '0') then
nextState <= stGetSettings3;
elsif not (syncNextSlice = '0' and syncWrite = '0'
and syncRead = '0') then
nextState <= stIdle;
end if;
stateOutput <= "1001";
when stGetSettings3 =>
nextState <= stGetSettings3;
if (syncNextSlice = '0' and syncWrite = '0'
and syncRead = '0') then
nextState <= stIdle;
getSettings <= '1';
Elsif not (syncNextSlice = '0' and syncWrite = '1'
and syncRead = '0') then
nextState <= stIdle;
End if;
stateOutput <= "1010";
when others =>
nextState <= stIdle;
clearInSliceNum <= '1';
end case;
end process;
end pctosraminterface_arch;
-------------------------------------------------------------------------------
-- History of major changes
-------------------------------------------------------------------------------
-- (15/02/2001) The VHDL for buffering the control signals has been
-- simplified. Additionally, we also buffer the value of DataIn. We only
-- change the value we are using for DataIn or the control signals when
-- EVERY level of flip-flops is holding the same set of values. This is just
-- a minor change to help ensure that any skew that the incoming signals
-- have relative to other incoming signals is removed. This change does
-- NOT affect the protocol between the PC and the board.
-- There are now only 4 levels of flip-flops instead of 5, to reduce the
-- amount of comparison logic needed.
-- (15/02/2001) pctosraminterface-sv06.vhd created from sv05.
-- (14/02/2001) The protocol for setting the address, writing a data value and
-- updating settings has now been changed. Instead of sending slice 0 of the
-- address or write data *before* we assert the control signals for the first
-- time, slice 0 of the address or write data must now be sent at the
-- *same time* as the control signals are first asserted. Overall this means
-- that we have shifted the timing of when each slice is sent to later in
-- time. Similarly, the protocol for updating settings has changed. You must
-- now do the following: set NextSlice to 1, set NextSlice to 0, set Write
-- to 1, set Write to 0 *and at the same time* place the new settings on
-- DataIn.
-- All this has been done so that we no longer have to remember the "old"
-- value of DataIn like we used to previously. The fact that we now buffer the
-- control signals through several levels of flip-flops meant that it was
-- becoming more awkward to remember the "old" value of DataIn. We now have no
-- need to remember the "old" value of DataIn.
-- (14/02/2001) pctosraminterface-sv05.vhd created from sv04.
-- (13/02/2001) We now buffer the control signals through 5 levels of
-- flip-flops.
-- (06/02/2001) The bug that caused the interface to incorrectly update its
-- settings has now been fixed. The protocol to update settings was made
-- to be more different from the protocols for reading and writing. This fixed
-- the problem.
-- (03/02/2001) pctosraminterface-sv04.vhd created from sv03.
-- (03/02/2001) Known bug: Occasionally the interface will incorrectly try
-- to update its settings. This probably means that the interface is not
-- robust enough when it comes to handling unexpected glitches in the
-- incoming control signals.
-- (29/01/2001) The sraminterface version
-- sram512kleft16bit50mhzreadreq-sv02.vhd has reverted to NOT registering
-- the read data internally. Therefore we must once again register the read
-- data ourselves. We know that when canRead goes high at the end of a read
-- then the read data will be valid at the end of the same clock cycle. It is
-- at that point (at the end of the cycle in which canRead returns to high)
-- that we register the read data.
-- (24/01/2001) Updated to use the sraminterfaces that need read requests.
-- Previously the sraminterface was always reading when it wasn't writing.
-- But versions of the file including the letters "readreq", such as
-- "sram512kleft16bit50mhzreadreq-sv01b.vhd" require a read request to
-- be made for a read to occur. The request is made by setting doRead high.
-- We also now use the canRead and canWrite signals to determine when a read
-- or write has completed. canRead and canWrite go high when new read and write
-- requests respectively can be made (and thus indicating that the current
-- read or write will be finished by the end of the clock cycle in which
-- canRead or canWrite goes high).
-- Also, although we no longer need to register readData (as the new
-- sraminterface registers it itself internally), we register it ourselves
-- anyway. See the comments in code.
-- (24/01/2001) pctosraminterface-sv03.vhd created from sv02.
-- The concept of "settings" has been introduced. See the comments in the
-- code.
-- (22/01/2001) DataIn now passes through 5 registers before its value is
-- used, rather than 6 as before. This is just to try and save a couple
-- of flip flops. It's probably an unnecessary and insignificant change.
-- (22/01/2001) Current address now increments by one after a write or a read.
-- This is designed to make bulk writes or reads to SRAM faster, since when
-- consecutive memory locations need to be accessed, the current address only
-- has to set once, at the start. It will then automatically increment after a
-- read or a write. If the PC programme does not want to access the next
-- consecutive location, it has to specifically set the current address.
-- (19/01/2001) Asynchronous control signals (Write, Read, NextSlice) are
-- now synchronised (i.e. put through flip-flops) before being read or used
-- in any way. Before this, the state-machine would often enter an unknown
-- state.
-- (18/01/2001) pctosraminterface-sv02.vhd created from
-- pctosraminterface-sv01.vhd. We stop looking for transitions of NextSlice
-- and look for the specific correct value. This is being done because in
-- testing it seemed that we sometimes missed transitions in NextSlice, which
-- really messes up the protocol. Now, if we don't see a change in NextSlice
-- during one clock cycle, we will see it in the next, or maybe even the one
-- after that. As long as we see it before the PC changes NextSlice again we
-- will be fine.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -