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

📄 sdramcntl.vhd

📁 xst3_video.ZIP是基于XILINX的XST3开发板的视频采集源码
💻 VHD
📖 第 1 页 / 共 4 页
字号:
  constant WRITE_CMD  : sdramCmd := "010000";
  constant PCHG_CMD   : sdramCmd := "001011";
  constant MODE_CMD   : sdramCmd := "000011";
  constant RFSH_CMD   : sdramCmd := "000111";

  -- SDRAM mode register
  -- the SDRAM is placed in a non-burst mode (burst length = 1) with a 3-cycle CAS
  subtype sdramMode is std_logic_vector(11 downto 0);
  constant MODE : sdramMode := "00" & "0" & "00" & "011" & "0" & "000";

  -- the host address is decomposed into these sets of SDRAM address components
  constant ROW_LEN : natural := log2(NROWS);  -- number of row address bits
  constant COL_LEN : natural := log2(NCOLS);  -- number of column address bits
  signal   bank    : std_logic_vector(ba'range);  -- bank address bits
  signal   row     : std_logic_vector(ROW_LEN - 1 downto 0);  -- row address within bank
  signal   col     : std_logic_vector(sAddr'range);  -- column address within row

  -- registers that store the currently active row in each bank of the SDRAM
  constant NUM_ACTIVE_ROWS            : integer := int_select(MULTIPLE_ACTIVE_ROWS = false, 1, 2**ba'length);
  type activeRowType is array(0 to NUM_ACTIVE_ROWS-1) of std_logic_vector(row'range);
  signal   activeRow_r, activeRow_x   : activeRowType;
  signal   activeFlag_r, activeFlag_x : std_logic_vector(0 to NUM_ACTIVE_ROWS-1);  -- indicates that some row in a bank is active
  signal   bankIndex                  : natural range 0 to NUM_ACTIVE_ROWS-1;  -- bank address bits
  signal   activeBank_r, activeBank_x : std_logic_vector(ba'range);  -- indicates the bank with the active row
  signal   doActivate                 : std_logic;  -- indicates when a new row in a bank needs to be activated

  -- there is a command bit embedded within the SDRAM column address
  constant CMDBIT_POS    : natural   := 10;  -- position of command bit
  constant AUTO_PCHG_ON  : std_logic := '1';  -- CMDBIT value to auto-precharge the bank
  constant AUTO_PCHG_OFF : std_logic := '0';  -- CMDBIT value to disable auto-precharge
  constant ONE_BANK      : std_logic := '0';  -- CMDBIT value to select one bank
  constant ALL_BANKS     : std_logic := '1';  -- CMDBIT value to select all banks

  -- status signals that indicate when certain operations are in progress
  signal wrInProgress       : std_logic;  -- write operation in progress
  signal rdInProgress       : std_logic;  -- read operation in progress
  signal activateInProgress : std_logic;  -- row activation is in progress

  -- these registers track the progress of read and write operations
  signal rdPipeline_r, rdPipeline_x : std_logic_vector(CAS_CYCLES+1 downto 0);  -- pipeline of read ops in progress
  signal wrPipeline_r, wrPipeline_x : std_logic_vector(0 downto 0);  -- pipeline of write ops (only need 1 cycle)

  -- registered outputs to host
  signal opBegun_r, opBegun_x             : std_logic;  -- true when SDRAM read or write operation is started
  signal hDOut_r, hDOut_x                 : std_logic_vector(hDOut'range);  -- holds data read from SDRAM and sent to the host
  signal hDOutOppPhase_r, hDOutOppPhase_x : std_logic_vector(hDOut'range);  -- holds data read from SDRAM   on opposite clock edge

  -- registered outputs to SDRAM
  signal cke_r, cke_x           : std_logic;  -- clock enable 
  signal cmd_r, cmd_x           : sdramCmd;  -- SDRAM command bits
  signal ba_r, ba_x             : std_logic_vector(ba'range);  -- SDRAM bank address bits
  signal sAddr_r, sAddr_x       : std_logic_vector(sAddr'range);  -- SDRAM row/column address
  signal sData_r, sData_x       : std_logic_vector(sDOut'range);  -- SDRAM out databus
  signal sDataDir_r, sDataDir_x : std_logic;  -- SDRAM databus direction control bit

begin

  -----------------------------------------------------------
  -- attach some internal signals to the I/O ports 
  -----------------------------------------------------------

  -- attach registered SDRAM control signals to SDRAM input pins
  (ce_n, ras_n, cas_n, we_n, dqmh, dqml) <= cmd_r;  -- SDRAM operation control bits
  cke                                    <= cke_r;  -- SDRAM clock enable
  ba                                     <= ba_r;  -- SDRAM bank address
  sAddr                                  <= sAddr_r;  -- SDRAM address
  sDOut                                  <= sData_r;  -- SDRAM output data bus
  sDOutEn                                <= YES when sDataDir_r = OUTPUT else NO;  -- output databus enable

  -- attach some port signals
  hDOut   <= hDOut_r;                   -- data back to host
  opBegun <= opBegun_r;                 -- true if requested operation has begun


  -----------------------------------------------------------
  -- compute the next state and outputs 
  -----------------------------------------------------------

  combinatorial : process(rd, wr, hAddr, hDIn, hDOut_r, sDIn, state_r, opBegun_x,
                          activeFlag_r, activeRow_r, activeBank_r, rdPipeline_r, wrPipeline_r,                          hDOutOppPhase_r, nopCntr_r, lock, rfshCntr_r, timer_r, rasTimer_r,
                          wrTimer_r, refTimer_r, cmd_r, cke_r, col, ba_r)  begin

    -----------------------------------------------------------
    -- setup default values for signals 
    -----------------------------------------------------------

    opBegun_x    <= NO;                 -- no operations have begun
    earlyOpBegun <= opBegun_x;
    cke_x        <= YES;                -- enable SDRAM clock
    cmd_x        <= NOP_CMD;            -- set SDRAM command to no-operation
    sDataDir_x   <= INPUT;              -- accept data from the SDRAM
    sData_x      <= hDIn(sData_x'range);  -- output data from host to SDRAM
    state_x      <= state_r;            -- reload these registers and flags
    activeFlag_x <= activeFlag_r;       --              with their existing values
    activeRow_x  <= activeRow_r;
    activeBank_x <= activeBank_r;
    rfshCntr_x   <= rfshCntr_r;

    -----------------------------------------------------------
    -- setup default value for the SDRAM address 
    -----------------------------------------------------------

    -- extract bank field from host address
    ba_x                    <= hAddr(ba'length + ROW_LEN + COL_LEN - 1 downto ROW_LEN + COL_LEN);
    if MULTIPLE_ACTIVE_ROWS = true then
      bank                  <= (others => '0');
      bankIndex             <= CONV_INTEGER(ba_x);
    else
      bank                  <= ba_x;
      bankIndex             <= 0;
    end if;
    -- extract row, column fields from host address
    row                     <= hAddr(ROW_LEN + COL_LEN - 1 downto COL_LEN);
    -- extend column (if needed) until it is as large as the (SDRAM address bus - 1)
    col                     <= (others => '0');  -- set it to all zeroes
    col(COL_LEN-1 downto 0) <= hAddr(COL_LEN-1 downto 0);
    -- by default, set SDRAM address to the column address with interspersed
    -- command bit set to disable auto-precharge
    sAddr_x                 <= col(col'high-1 downto CMDBIT_POS) & AUTO_PCHG_OFF
                               & col(CMDBIT_POS-1 downto 0);

    -----------------------------------------------------------
    -- manage the read and write operation pipelines
    -----------------------------------------------------------

    -- determine if read operations are in progress by the presence of
    -- READ flags in the read pipeline 
    if rdPipeline_r(rdPipeline_r'high downto 1) /= 0 then
      rdInProgress <= YES;
    else
      rdInProgress <= NO;
    end if;
    rdPending      <= rdInProgress;     -- tell the host if read operations are in progress

    -- enter NOPs into the read and write pipeline shift registers by default
    rdPipeline_x    <= NOP & rdPipeline_r(rdPipeline_r'high downto 1);
    wrPipeline_x(0) <= NOP;

    -- transfer data from SDRAM to the host data register if a read flag has exited the pipeline
    -- (the transfer occurs 1 cycle before we tell the host the read operation is done)
    if rdPipeline_r(1) = READ then
      hDOutOppPhase_x <= sDIn(hDOut'range);  -- gets value on the SDRAM databus on the opposite phase
      if IN_PHASE then
        -- get the SDRAM data for the host directly from the SDRAM if the controller and SDRAM are in-phase
        hDOut_x       <= sDIn(hDOut'range);
      else
        -- otherwise get the SDRAM data that was gathered on the previous opposite clock edge
        hDOut_x       <= hDOutOppPhase_r(hDOut'range);
      end if;
    else
      -- retain contents of host data registers if no data from the SDRAM has arrived yet
      hDOutOppPhase_x <= hDOutOppPhase_r;
      hDOut_x         <= hDOut_r;
    end if;

    done   <= rdPipeline_r(0) or wrPipeline_r(0);  -- a read or write operation is done
    rdDone <= rdPipeline_r(0);          -- SDRAM data available when a READ flag exits the pipeline 

    -----------------------------------------------------------
    -- manage row activation
    -----------------------------------------------------------

    -- request a row activation operation if the row of the current address
    -- does not match the currently active row in the bank, or if no row
    -- in the bank is currently active
    if (bank /= activeBank_r) or (row /= activeRow_r(bankIndex)) or (activeFlag_r(bankIndex) = NO) then
      doActivate <= YES;
    else
      doActivate <= NO;
    end if;

    -----------------------------------------------------------
    -- manage self-refresh
    -----------------------------------------------------------

    -- enter self-refresh if neither a read or write is requested for MAX_NOP consecutive cycles.
    if (rd = YES) or (wr = YES) then
      -- any read or write resets NOP counter and exits self-refresh state
      nopCntr_x  <= 0;
      doSelfRfsh <= NO;
    elsif nopCntr_r /= MAX_NOP then
      -- increment NOP counter whenever there is no read or write operation 
      nopCntr_x  <= nopCntr_r + 1;
      doSelfRfsh <= NO;
    else
      -- start self-refresh when counter hits maximum NOP count and leave counter unchanged
      nopCntr_x  <= nopCntr_r;
      doSelfRfsh <= YES;
    end if;

    -----------------------------------------------------------
    -- update the timers 
    -----------------------------------------------------------

    -- row activation timer
    if rasTimer_r /= 0 then
      -- decrement a non-zero timer and set the flag
      -- to indicate the row activation is still inprogress
      rasTimer_x         <= rasTimer_r - 1;
      activateInProgress <= YES;
    else
      -- on timeout, keep the timer at zero     and reset the flag
      -- to indicate the row activation operation is done
      rasTimer_x         <= rasTimer_r;
      activateInProgress <= NO;
    end if;

    -- write operation timer            
    if wrTimer_r /= 0 then
      -- decrement a non-zero timer and set the flag
      -- to indicate the write operation is still inprogress
      wrTimer_x    <= wrTimer_r - 1;
      wrInPRogress <= YES;
    else
      -- on timeout, keep the timer at zero and reset the flag that
      -- indicates a write operation is in progress
      wrTimer_x    <= wrTimer_r;
      wrInPRogress <= NO;
    end if;

    -- refresh timer            
    if refTimer_r /= 0 then
      refTimer_x <= refTimer_r - 1;
    else
      -- on timeout, reload the timer with the interval between row refreshes
      -- and increment the counter for the number of row refreshes that are needed
      refTimer_x <= REF_CYCLES;
      if ENABLE_REFRESH then
        rfshCntr_x <= rfshCntr_r + 1;
      else
        rfshCntr_x <= 0; -- refresh never occurs if this counter never gets above zero
      end if;
    end if;

    -- main timer for sequencing SDRAM operations               
    if timer_r /= 0 then
      -- decrement the timer and do nothing else since the previous operation has not completed yet.
      timer_x <= timer_r - 1;
      status  <= "0000";
    else
      -- the previous operation has completed once the timer hits zero
      timer_x <= timer_r;               -- by default, leave the timer at zero

      -----------------------------------------------------------
      -- compute the next state and outputs 
      -----------------------------------------------------------
      case state_r is

        -----------------------------------------------------------
        -- let clock stabilize and then wait for the SDRAM to initialize 
        -----------------------------------------------------------
        when INITWAIT =>
          if lock = YES then
                                        -- wait for SDRAM power-on initialization once the clock is stable
            timer_x <= INIT_CYCLES;     -- set timer for initialization duration
            state_x <= INITPCHG;
          else
                                        -- disable SDRAM clock and return to this state if the clock is not stable

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -