⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdramcntl.vhd

📁 xst3_video.ZIP是基于XILINX的XST3开发板的视频采集源码
💻 VHD
📖 第 1 页 / 共 4 页
字号:
-- 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 + -