📄 pctosraminterface-sv06.vhd
字号:
-------------------------------------------------------------------------------
-- pctosraminterface-sv06.vhd
--
-- Author(s): James Brennan
-- Created: 15 Feb 2001
-- Last Modified: 15 Feb 2001
--
-- Provides an interface to the SRAM controller that allows the PC to read
-- and write to the SRAM via the parallel port.
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity pctosraminterface is
port (
CLK: in STD_LOGIC;
Resetn : in STD_LOGIC;
Write: in STD_LOGIC;
Read: in STD_LOGIC;
NextSlice: in STD_LOGIC;
DataIn: in STD_LOGIC_VECTOR (4 downto 0);
DataOut: out STD_LOGIC_VECTOR (3 downto 0);
doSRAMWrite: out STD_LOGIC;
doSRAMRead: out STD_LOGIC;
canWrite: in STD_LOGIC;
canRead: in STD_LOGIC;
writeAddr: out STD_LOGIC_VECTOR (18 downto 0);
writeData: out STD_LOGIC_VECTOR (15 downto 0);
readAddr: out STD_LOGIC_VECTOR (18 downto 0);
readData: in STD_LOGIC_VECTOR (15 downto 0);
-- Ports used when embedding this interface in
-- a user design:
active : out STD_LOGIC;
-- Ports we expose for debugging purposes:
-- It was originally intended that these ports would be
-- removed, but it has been more convenient to leave them in:
portInSliceNum : out STD_LOGIC_VECTOR(1 downto 0);
portOutSliceNum : out STD_LOGIC_VECTOR(1 downto 0);
stateOutput : out STD_LOGIC_VECTOR(3 downto 0)
);
end pctosraminterface;
architecture pctosraminterface_arch of pctosraminterface is
-- ========================================
-- Architecture declarations:
-- ========================================
-- Synchronous versions of the control inputs.
-- We pass each control signal and the value on DataIn
-- through a series of flip-flops. To simply the VHDL
-- we concatenate the control signals and DataIn into
-- a single STD_LOGIC_VECTOR. Only we the each level
-- of flip-flops has the same value do we use the
-- value of the control signals and/or DataIn.
signal asyncInputs : STD_LOGIC_VECTOR(7 downto 0);
signal syncInputs1, syncInputs2,
syncInputs3 : STD_LOGIC_VECTOR(7 downto 0) ;
-- Synchronous versions of the control inputs that
-- we actually use. For each control signal, when
-- each flip-flop in the corresponding chain holds the
-- same value, we copy that value into one of the
-- following signals:
signal syncWrite : STD_LOGIC;
signal syncRead : STD_LOGIC;
signal syncNextSlice : STD_LOGIC;
-- Register declarations:
signal dataInReg : STD_LOGIC_VECTOR(4 downto 0);
signal curAddrReg : STD_LOGIC_VECTOR(18 downto 0);
signal writeDataReg : STD_LOGIC_VECTOR(15 downto 0);
signal readDataReg : STD_LOGIC_VECTOR(15 downto 0);
-- Clock-enable signals for the registers:
signal regDataIn : STD_LOGIC;
signal regCurAddr : STD_LOGIC;
signal regWriteData : STD_LOGIC;
signal regReadData : STD_LOGIC;
-- Signal to indicate which "slice" we are now waiting
-- to receive (when we are receiving an address or a
-- data value from the PC):
-- An address is transmitted in three slices of 5 bits
-- and one slice of 4 bits.
-- Data values are transmitted in four slices of 4 bits.
-- The least significant slice (the slice containing the
-- the least significant bit) is always transmitted
-- first.
signal inSliceNum : STD_LOGIC_VECTOR(1 downto 0);
-- Signal to indicate the current "slice" when
-- we are sending data to the PC.
signal outSliceNum : STD_LOGIC_VECTOR(1 downto 0);
-- Other control signals:
signal incCurAddr : STD_LOGIC;
signal incInSliceNum : STD_LOGIC;
signal incOutSliceNum : STD_LOGIC;
signal clearInSliceNum : STD_LOGIC;
signal clearOutSliceNum : STD_LOGIC;
-- Signal declarations for settings:
-- Settings are simple 1-bit signals that can be thought of
-- as "preferences" or "configuration data" in hardware.
-- The PC can set the state of each of these bits. The idea
-- is that by setting or clearing these bits, the PC can
-- control the behaviour of this PC-to-SRAM interface.
-- When getSettings = '1', on the next rising clock edge,
-- the value in dataInReg
-- (i.e. effectively the value on DataIn) is copied into
-- the current settings. This means we can currently
-- have a maximum of 5 bits worth of settings.
signal getSettings : STD_LOGIC;
-- When pcControlEnabled is '1', this PC-to-SRAM interface
-- requests exclusive access to SRAM. When pcControlEnable = '0',
-- this PC-to-SRAM interface gives up its access to SRAM.
-- This setting is visible on the output port "active".
-- This signal is designed to be used (with supporting entities
-- and a supporting top-level) to allow this interface
-- and a different arbitrary design to share access to the
-- SRAM. A user design simply accesses SRAM through a special
-- top-level entity. Most of the time this entity allows
-- full SRAM access to the user design. When pcControlEnabled
-- = '1', it is expected that the user design will be
-- "disconnected" from SRAM and this interface "connected" in its
-- place. This is to allow to contents of SRAM to be accessed
-- on the PC without having to download a new bit file.
-- pcControlEnabled is to be loaded with bit 0 of dataInReg.
signal pcControlEnabled : STD_LOGIC;
-- Signals for FSM controller:
type typeStateType is (stIdle, stGetAddr1, stDoWrite1, stDoWrite2,
stDoRead1, stDoRead2, stDoRead3,
stGetSettings1, stGetSettings2, stGetSettings3);
signal presState, nextState: typeStateType;
begin
-- ========================================
-- Architecture body:
-- ========================================
-- ========================================
-- Combinational signals
-- ========================================
-- Debug connections:
portInSliceNum <= inSliceNum;
portOutSliceNum <= outSliceNum;
writeAddr <= curAddrReg;
readAddr <= curAddrReg;
writeData <= writeDataReg;
-- We concatenate the control signals and DataIn into one
-- vector for the purposes of passing it through several
-- levels of flip-flops for synchronization purposes:
asyncInputs <= NextSlice & Read & Write & DataIn;
-- Multiplex the data presented on DataOut:
with outSliceNum select
DataOut <= readDataReg(3 downto 0) when "00",
readDataReg(7 downto 4) when "01",
readDataReg(11 downto 8) when "10",
readDataReg(15 downto 12) when others;
active <= pcControlEnabled;
-- ========================================
-- Process for reset and clock-edge events
-- ========================================
process(CLK, Resetn)
begin
if Resetn = '0' then
-- Set defaults for all signals not controlled
-- by the FSM controller.
presState <= stIdle;
syncInputs1 <= (others => '0');
syncInputs2 <= (others => '0');
syncInputs3 <= (others => '0');
syncWrite <= '0';
syncRead <= '0';
syncNextSlice <= '0';
dataInReg <= (others => '0');
curAddrReg <= (others => '0');
writeDataReg <= (others => '0');
readDataReg <= (others => '0');
inSliceNum <= (others => '0');
outSliceNum <= (others => '0');
pcControlEnabled <= '0';
elsif CLK'EVENT and CLK = '1' then
-- Update synchronous values of the control
-- signals:
syncInputs1 <= asyncInputs;
syncInputs2 <= syncInputs1;
syncInputs3 <= syncInputs2;
-- For the chain of flip-flops associated with
-- each of the eight incoming asynchronous inputs,
-- we update the "offical" synchronised value of the
-- input signal (which we actually use in the
-- state machine below) only if every flip-flop
-- in the chain holds the same value:
if (syncInputs1 = syncInputs2) and
(syncInputs2 = syncInputs3) then
syncNextSlice <= syncInputs3(7);
syncRead <= syncInputs3(6);
syncWrite <= syncInputs3(5);
dataInReg <= syncInputs3(4 downto 0);
end if;
-- Handle the clock-enabling of each register:
if incCurAddr = '1' then
curAddrReg <= curAddrReg + 1;
elsif regCurAddr = '1' then
case inSliceNum is
when "00" =>
curAddrReg(4 downto 0) <= dataInReg(4 downto 0);
when "01" =>
curAddrReg(9 downto 5) <= dataInReg(4 downto 0);
when "10" =>
curAddrReg(14 downto 10) <= dataInReg(4 downto 0);
when others =>
curAddrReg(18 downto 15) <= dataInReg(3 downto 0);
end case;
end if;
if regWriteData = '1' then
case inSliceNum is
when "00" =>
writeDataReg(3 downto 0) <= dataInReg(3 downto 0);
when "01" =>
writeDataReg(7 downto 4) <= dataInReg(3 downto 0);
when "10" =>
writeDataReg(11 downto 8) <= dataInReg(3 downto 0);
when others =>
writeDataReg(15 downto 12) <= dataInReg(3 downto 0);
end case;
end if;
if regReadData = '1' then
-- For debug purposes we load the readDataReg directly with the
-- writeDataReg.
-- readDataReg <= writeDataReg;
-- readDataReg(15) <= '0';
-- readDataReg(14 downto 0) <= curAddrReg(18 downto 4);
readDataReg <= readData;
end if;
if clearInSliceNum = '1' then
inSliceNum <= (others => '0');
elsif incInSliceNum = '1' then
inSliceNum <= inSliceNum + 1;
end if;
if clearOutSliceNum = '1' then
outSliceNum <= (others => '0');
elsif incOutSliceNum = '1' then
outSliceNum <= outSliceNum + 1;
end if;
-- Handle the updating of settings:
if getSettings = '1' then
pcControlEnabled <= dataInReg(0);
end if;
-- Update current state for the controller FSM.
presState <= nextState;
end if;
end process;
-- ========================================
-- Process for FSM of controller
-- ========================================
process(presState, syncWrite, syncRead, syncNextSlice,
inSliceNum, outSliceNum, canWrite, canRead)
begin
-- Set the defaults for all the signals this FSM
-- controls:
regDataIn <= '0';
regCurAddr <= '0';
regWriteData <= '0';
regReadData <= '0';
incCurAddr <= '0';
incInSliceNum <= '0';
incOutSliceNum <= '0';
clearInSliceNum <= '0';
clearOutSliceNum <= '0';
doSRAMWrite <= '0';
doSRAMRead <= '0';
getSettings <= '0';
-- Set default value of stateOutput:
stateOutput <= "1111";
case presState is
when stIdle =>
nextState <= stIdle;
if syncNextSlice = '1' then
if syncWrite = '1' and syncRead = '1' then
nextState <= stGetAddr1;
-- Register slice 0:
regCurAddr <= '1';
-- Increment slice number so that we're ready
-- for the next slice:
incInSliceNum <= '1';
elsif syncWrite = '1' then
nextState <= stDoWrite1;
-- Register slice 0:
regWriteData <= '1';
-- Increment slice number so that we're ready
-- for the next slice:
incInSliceNum <= '1';
elsif syncRead = '1' then
nextState <= stDoRead1;
clearOutSliceNum <= '1';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -