📄 sdramcntl.vhd
字号:
-- Company : XESS Corp.
-- Engineer : Dave Vanden Bout
-- Creation Date : 06/01/2005
-- Copyright : 2005, XESS Corp
-- Tool Versions : WebPACK 6.3.03i
--
-- Description:
-- Dual-port front-end for SDRAM controller. Supports two
-- independent I/O ports to the SDRAM.
--
-- Revision:
-- 1.1.0
--
-- Additional Comments:
-- 1.1.0:
-- Fixed a problem where dualport locked up ifa port had control
-- but had no pending operation to signal done so a switch could be
-- made to the other port.
-- 1.0.0:
-- Initial release.
--
-- License:
-- This code can be freely distributed and modified as long as
-- this header is not removed.
--------------------------------------------------------------------
library IEEE, UNISIM;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
use WORK.common.all;
entity dualport is
generic(
PIPE_EN : boolean := false; -- enable pipelined read operations
PORT_TIME_SLOTS : std_logic_vector(15 downto 0) := "1111000011110000";
DATA_WIDTH : natural := 16; -- host & SDRAM data width
HADDR_WIDTH : natural := 23 -- host-side address width
);
port(
clk : in std_logic; -- master clock
-- host-side port 0
rst0 : in std_logic; -- reset
rd0 : in std_logic; -- initiate read operation
wr0 : in std_logic; -- initiate write operation
earlyOpBegun0 : out std_logic; -- read/write op has begun (async)
opBegun0 : out std_logic; -- read/write op has begun (clocked)
rdPending0 : out std_logic; -- true if read operation(s) are still in the pipeline
done0 : out std_logic; -- read or write operation is done
rdDone0 : out std_logic; -- read operation is done and data is available
hAddr0 : in std_logic_vector(HADDR_WIDTH-1 downto 0); -- address from host to SDRAM
hDIn0 : in std_logic_vector(DATA_WIDTH-1 downto 0); -- data from host to SDRAM
hDOut0 : out std_logic_vector(DATA_WIDTH-1 downto 0); -- data from SDRAM to host
status0 : out std_logic_vector(3 downto 0); -- diagnostic status of the SDRAM controller FSM
-- host-side port 1
rst1 : in std_logic;
rd1 : in std_logic;
wr1 : in std_logic;
earlyOpBegun1 : out std_logic;
opBegun1 : out std_logic;
rdPending1 : out std_logic;
done1 : out std_logic;
rdDone1 : out std_logic;
hAddr1 : in std_logic_vector(HADDR_WIDTH-1 downto 0);
hDIn1 : in std_logic_vector(DATA_WIDTH-1 downto 0);
hDOut1 : out std_logic_vector(DATA_WIDTH-1 downto 0);
status1 : out std_logic_vector(3 downto 0);
-- SDRAM controller port
rst : out std_logic;
rd : out std_logic;
wr : out std_logic;
earlyOpBegun : in std_logic;
opBegun : in std_logic;
rdPending : in std_logic;
done : in std_logic;
rdDone : in std_logic;
hAddr : out std_logic_vector(HADDR_WIDTH-1 downto 0);
hDIn : out std_logic_vector(DATA_WIDTH-1 downto 0);
hDOut : in std_logic_vector(DATA_WIDTH-1 downto 0);
status : in std_logic_vector(3 downto 0)
);
end dualport;
architecture arch of dualport is
-- The door signal controls whether the read/write signal from the active port
-- is allowed through to the read/write inputs of the SDRAM controller.
type doorState is (OPENED, CLOSED);
signal door_r, door_x : doorState;
-- The port signal indicates which port is connected to the SDRAM controller.
type portState is (PORT0, PORT1);
signal port_r, port_x : portState;
signal switch : std_logic; -- indicates that the active port should be switched
signal inProgress : std_logic; -- the active port has a read/write op in-progress
signal rd_i : std_logic; -- read signal to the SDRAM controller (internal copy)
signal wr_i : std_logic; -- write signal to the SDRAM controller (internal copy)
signal earlyOpBegun0_i, earlyOpBegun1_i : std_logic; -- (internal copies)
signal slot_r, slot_x : std_logic_vector(PORT_TIME_SLOTS'range); -- time-slot allocation shift-register
begin
----------------------------------------------------------------------------
-- multiplex the SDRAM controller port signals to/from the dual host-side ports
----------------------------------------------------------------------------
-- send the SDRAM controller the address and data from the currently active port
hAddr <= hAddr0 when port_r = PORT0 else hAddr1;
hDIn <= hDIn0 when port_r = PORT0 else hDIn1;
-- both ports get the data from the SDRAM but only the active port will use it
hDOut0 <= hDOut;
hDOut1 <= hDOut;
-- send the SDRAM controller status to the active port and give the inactive port an inactive status code
status0 <= status when port_r = PORT0 else "1111";
status1 <= status when port_r = PORT1 else "1111";
-- either port can reset the SDRAM controller
rst <= rst0 or rst1;
-- apply the read signal from the active port to the SDRAM controller only if the door is open.
rd_i <= rd0 when (port_r = PORT0) and (door_r = OPENED) else
rd1 when (port_r = PORT1) and (door_r = OPENED) else
NO;
rd <= rd_i;
-- apply the write signal from the active port to the SDRAM controller only if the door is open.
wr_i <= wr0 when (port_r = PORT0) and (door_r = OPENED) else
wr1 when (port_r = PORT1) and (door_r = OPENED) else
NO;
wr <= wr_i;
-- send the status signals for various SDRAM controller operations back to the active port
earlyOpBegun0_i <= earlyOpBegun when port_r = PORT0 else NO;
earlyOpBegun0 <= earlyOpBegun0_i;
earlyOpBegun1_i <= earlyOpBegun when port_r = PORT1 else NO;
earlyOpBegun1 <= earlyOpBegun1_i;
rdPending0 <= rdPending when port_r = PORT0 else NO;
rdPending1 <= rdPending when port_r = PORT1 else NO;
done0 <= done when port_r = PORT0 else NO;
done1 <= done when port_r = PORT1 else NO;
rdDone0 <= rdDone when port_r = PORT0 else NO;
rdDone1 <= rdDone when port_r = PORT1 else NO;
----------------------------------------------------------------------------
-- Indicate when the active port needs to be switched. A switch occurs if
-- a read or write operation is requested on the port that is not currently active and:
-- 1) no R/W operation is being performed on the active port or
-- 2) a R/W operation is in progress on the active port, but the time-slot allocation
-- register is giving precedence to the inactive port. (The R/W operation on the
-- active port will be completed before the switch is made.)
-- This rule keeps the active port from hogging all the bandwidth.
----------------------------------------------------------------------------
switch <= (rd0 or wr0) when (port_r = PORT1) and (((rd1 = NO) and (wr1 = NO)) or (slot_r(0) = '0')) else
(rd1 or wr1) when (port_r = PORT0) and (((rd0 = NO) and (wr0 = NO)) or (slot_r(0) = '1')) else
NO;
----------------------------------------------------------------------------
-- Indicate when an operation on the active port is in-progress and
-- can't be interrupted by a switch to the other port. (Only read operations
-- are looked at since write operations always complete in one cycle once they
-- are initiated.)
----------------------------------------------------------------------------
inProgress <= rdPending or (rd_i and earlyOpBegun);
----------------------------------------------------------------------------
-- Update the time-slot allocation shift-register. The port with priority is indicated by the
-- least-significant bit of the register. The register is rotated right if:
-- 1) the current R/W operation has started, and
-- 2) both ports are requesting R/W operations (indicating contention), and
-- 3) the currently active port matches the port that currently has priority.
-- Under these conditions, the current time slot port allocation has been used so
-- the shift register is rotated right to bring the next port time-slot allocation
-- bit into play.
----------------------------------------------------------------------------
slot_x <= slot_r(0) & slot_r(slot_r'high downto 1) when (earlyOpBegun = YES) and
( ((rd0 = YES) or (wr0 = YES)) and ((rd1 = YES) or (wr1 = YES)) ) and
( ((port_r = PORT0) and (slot_r(0) = '0')) or ((port_r = PORT1) and (slot_r(0) = '1')) )
else slot_r;
----------------------------------------------------------------------------
-- Determine which port will be active on the next cycle. The active port is switched if:
-- 1) there are no pending operations in progress, and
-- 2) the port switch indicator is active.
----------------------------------------------------------------------------
port_process : process(port_r, inProgress, switch, done)
begin
port_x <= port_r; -- by default, the active port is not changed
case port_r is
when PORT0 =>
if (inProgress = NO) and (switch = YES) then
port_x <= PORT1;
end if;
when PORT1 =>
if (inProgress = NO) and (switch = YES) then
port_x <= PORT0;
end if;
when others =>
port_x <= port_r;
end case;
end process port_process;
-----------------------------------------------------------
-- Determine if the door is open for the active port to initiate new R/W operations to
-- the SDRAM controller. If the door is open and R/W operations are in progress but
-- a switch to the other port is indicated, then the door is closed to prevent any
-- further R/W operations from the active port. The door is re-opened once all
-- in-progress operations are completed, at which time the switch to the other port
-- is also completed so it can issue its own R/W commands.
-----------------------------------------------------------
door_process : process(door_r, inProgress, switch)
begin
door_x <= door_r; -- by default, the door remains as it is
case door_r is
when OPENED =>
if (inProgress = YES) and (switch = YES) then
door_x <= CLOSED;
end if;
when CLOSED =>
if inProgress = NO then
door_x <= OPENED;
end if;
when others =>
door_x <= door_r;
end case;
end process door_process;
-----------------------------------------------------------
-- update registers on the appropriate clock edge
-----------------------------------------------------------
update : process(rst0, rst1, clk)
begin
if (rst0 = YES) or (rst1 = YES) then
-- asynchronous reset
door_r <= CLOSED;
port_r <= PORT0;
slot_r <= PORT_TIME_SLOTS;
opBegun0 <= NO;
opBegun1 <= NO;
elsif rising_edge(clk) then
door_r <= door_x;
port_r <= port_x;
slot_r <= slot_x;
-- opBegun signals are cycle-delayed versions of earlyOpBegun signals.
-- We can't use the actual opBegun signal from the SDRAM controller
-- because it would be turned off if the active port was switched on the
-- cycle immediately after earlyOpBegun went active.
opBegun0 <= earlyOpBegun0_i;
opBegun1 <= earlyOpBegun1_i;
end if;
end process update;
end arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -