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

📄 ddr_sdr.vhd

📁 ddr verilog代码,实现DDR内存控制
💻 VHD
📖 第 1 页 / 共 3 页
字号:
         variable ps : integer;
      begin
         ps := +30;   -- for synthesis only, values between 0 and +60  are OK for XILINX VirtexII Development Board
                      -- and CESYS XV2DDR board
         -- pragma translate_off
         ps := +30;    -- for simulation only
         -- pragma translate_on
         return ps;
      end;

   begin
      
      rst_int_n  <= not srst_sys_q;
      sys_rst_qn <= not srst_sys_q;

      sys_clk_out <= sys_clk; -- for other modules inside the FPGA
      
      dcm0: entity work.my_dcm generic map (G_CLOCK_FEEDBACK => "1X",
                                            G_CLKIN_PERIOD   => "10.0",
                                            G_CLKOUT_PHASE_SHIFT => "FIXED",
                                            G_PHASE_SHIFT    => func_phase_shift )
         
       
         port map ( clkin => clk,
                    clkfb => clk_fb,
                    clk0  => clk_int,
                    clkdv => open,
                    clk2x => open,
                    clk90 => open,
                    clk180 => open,
                    clk270 => open,
                    rst   => dcm_rst_q,
                    locked => locked(0)
                    );

      dcm1: entity work.my_dcm generic map (G_CLOCK_FEEDBACK => "1X",
                                            G_CLKIN_PERIOD   => "10.0",
                                            G_CLKOUT_PHASE_SHIFT => "FIXED",
                                            G_PHASE_SHIFT    => 0 )
         
         
         port map ( clkin => clk,
                    clkfb => sys_clk,
                    clk0  => fpga_clk,
                    clkdv => open,
                    clk2x => open,
                    clk90 => open,
                    clk180 => open,
                    clk270 => fpga_clk270,
                    rst   => dcm_rst_q,
                    locked => locked(1)
                    );


      bufg11: bufg
         port map ( o  => sys_clk,  
                    i  => fpga_clk);

      bufg12: bufg
         port map ( o  => sys_clk270,  
                    i  => fpga_clk270);

      -------------------------------------------------------
      -- User-Interface 
      -------------------------------------------------------
      user_if_inst : user_if
         port map (
            rst_int_n       => rst_int_n,
            sys_clk         => sys_clk,
            cmd             => cmd,
            addr            => addr,
            busy_q          => busy_q,
            cmd_vld         => cmd_vld,
            init_finished   => init_finished_q,
            new_cmd_q       => new_cmd_q,
            new_cmd_ack     => new_cmd_ack_q,
            do_prech_q      => do_prech_q,
            do_wait_q       => do_wait_q, 
            cmd_q           => cmd_ui_q,
            addr_q          => addr_ui_q
         );


      process (sys_clk, rst_int_n) is
         variable start_wr : boolean;
         variable start_rd : boolean;
      begin 
         if rst_int_n = '0' then  
            state_q       <= IDLE;
            sdr_if_q      <= COMMAND(NOP); 
            sdr_if2_q     <= COMMAND(NOP);
            ld_init_cnt_q <= false;
            ct0_q         <= false;
            ct_cnt_q      <= 0;
            ld_ct_cnt_q   <= false;
            ld_dll_cnt_q  <= false;
            second_refresh_q <= false;

            a_int_q    <= (others => '0');
            a_int2_q   <= (others => '0');
            cs_int_qn  <= '1';
            ba_int_q   <= (others=>'0');
            ba_int2_q  <= (others=>'0');
            cke_int_q  <= '0';
            cke_int2_q <= '0';
    
            z_q          <= '0';
            bus_switch_q <= (others => '0');
            
            rd_ena_q     <= false;
            wr_ena_q     <= '0';
            wr_ena2_q    <= '0';
            wr_ena3_q    <= '0';
            del_cnt_q    <= 0;
            del0_q       <= true;
            ld_del_cnt_q <= false;
            w_srg_q      <= (others=>'0');
            mux_q        <= NORMAL;
            shift_q(0)   <= (others=>'0');
            row_adr_q    <= (others=>'0');
            col_adr_q    <= (others=>'0');
            tras_cnt_q    <= 0;
            init_finished_q <= false;
            new_cmd_ack_q   <= false;
           
         elsif rising_edge(sys_clk) then
         
            -- Default's for variables
            start_wr := false;
            start_rd := false;
            
            -- default CMD
            sdr_if_q  <= COMMAND(NOP);
            a_int_q   <= (others => '0');
            cs_int_qn <= '1';

            ld_ct_cnt_q     <= false;
            ld_dll_cnt_q    <= false;
            ld_init_cnt_q   <= false;
            init_finished_q <= false;
            new_cmd_ack_q   <= false;
            ld_del_cnt_q    <= false;
            
            -- MAIN FSM to generate Controller commands and timing
            case state_q is

               when IDLE =>
                  mux_q <= NORMAL;
                  if locked = "11" then
                     -- start of ddr-sdram initialization when dcms are locked
                     assert cke_int_q='0' report "cke_q error!" severity failure;
                     ld_init_cnt_q <= true;
                     state_q       <= WAIT_200us;
                  end if;
                  
               when WAIT_200us =>
                  if init_cnt1_q then
                     cke_int_q <= '1';                     
                  end if;
                  
                  if init_cnt0_q then
                     ld_ct_cnt_q <= true;
                     sdr_if_q    <= COMMAND(PRECHARGE);
                     a_int_q(AUTO_PRECHARGE) <= '1';  -- precharge all
                     state_q     <= INIT1_PRECHARGE;
                  end if;

               when INIT1_PRECHARGE =>
                  if ct0_q then
                     sdr_if_q    <= COMMAND(EXT_MODE);  
                     a_int_q     <= EXT_MODE_REG;
                     ba_int_q    <= EXT_MODE_REG_BANK;
                     ld_ct_cnt_q <= true;
                     state_q     <= INIT_EXT_MODE;
                  end if;

               when INIT_EXT_MODE =>
                  if ct0_q then
                     -- set MODE Register
                     a_int_q     <= MODE_REG_DLL_RST;
                     sdr_if_q    <= COMMAND(MODE);
                     state_q     <= INIT1_MODE;
                     ba_int_q    <= BASE_MODE_REG_BANK;
                     ld_ct_cnt_q <= true;
                  end if;

               when INIT1_MODE =>
                  if ct0_q then
                     ld_dll_cnt_q <= true;
                     state_q      <= WAIT_DLL;
                  end if;

               when WAIT_DLL =>
                  -- wait 200 clk cycles
                  if dll_cnt0_q then
                     state_q     <= INIT2_PRECHARGE;
                     sdr_if_q    <= COMMAND(PRECHARGE);
                     ld_ct_cnt_q <= true;
                     a_int_q(AUTO_PRECHARGE) <= '1';  -- precharge all
                  end if;

               when INIT2_PRECHARGE =>
                  if ct0_q then
                     sdr_if_q    <= COMMAND(REFRESH);
                     ld_ct_cnt_q <= true;
                     state_q     <= INIT_REFRESH;
                  end if;
                
               when INIT_REFRESH =>
                  if ct0_q then
                     sdr_if_q         <= COMMAND(REFRESH);
                     ld_ct_cnt_q      <= true;
                     second_refresh_q <= true;
                     
                     if second_refresh_q then
                        state_q     <= INIT2_MODE;
                        sdr_if_q    <= COMMAND(MODE);
                        ld_ct_cnt_q <= true;
                        -- set MODE Reg again (DLL enabled)
                        a_int_q  <= MODE_REG_DLL_ENA;
                        ba_int_q <= BASE_MODE_REG_BANK;
                     end if;
                  end if;
                  
               when INIT2_MODE =>
                  if ct0_q then
                     state_q         <= ST_WAIT_CMD;
                     init_finished_q <= true;
                  end if; -- End of Initialization
               
               -- Main State for COMMAND processing ------------------------------------------------------
               when ST_WAIT_CMD =>
                  ba_int_q <= addr_ui_q(addr_ui_q'LEFT-DDR_ADDR_WIDTH  downto addr_ui_q'LEFT -DDR_ADDR_WIDTH - (DDR_BANK_WIDTH-1));

                  -- Store Row and Column address as long as the command is processed
                  row_adr_q <= addr_ui_q(addr_ui_q'LEFT downto addr_ui_q'LEFT -DDR_ADDR_WIDTH+1); 
                  col_adr_q <= addr_ui_q(addr_ui_q'RIGHT+DDR_ADDR_WIDTH-1 downto 0);
                  
                  if new_cmd_q then

                     if do_wait_q and w_srg_q(0)='1'then -- Read2Write or Write2Read
                        null;
                     else
                        -- Acknowledge the command immediately
                        new_cmd_ack_q <= true;
                  
                        case cmd_ui_q is
                        
                           when NOP_CMD =>
                              null;
                              
                           when RD_CMD => -- READ -------------------------
                              mux_q     <= NORMAL;
                           
                              if do_prech_q then
                                 state_q <= RD_PRECH;
                              else
                                 start_rd  := true;
                                 a_int_q   <= addr_ui_q(addr_ui_q'RIGHT+DDR_ADDR_WIDTH-1 downto 0) ; -- COL
                                 sdr_if_q  <= COMMAND(BURST_RD); -- Kommando setzen
                                 state_q   <= ST_READ1;
                              end if;
                           
                           when WR_CMD => -- WRITE ------------------------
                              mux_q <= DELAYED;
                  
                              if do_prech_q then
                                 state_q     <= WR_PRECH;
                              else
                                 start_wr := true;
                                 -- hier direkt von addr_ui_q laden
                                 a_int_q     <= addr_ui_q(addr_ui_q'RIGHT+DDR_ADDR_WIDTH-1 downto 0) ; -- COL
                                 sdr_if_q    <= COMMAND(BURST_WR); -- Kommando setzen
                                 state_q     <= ST_WRITE1;
                              end if;
                              
                           when RFSH_CMD => -- FORCED REFRESH -------------------
                              mux_q          <= NORMAL;
                              state_q        <= ST_RFSH_0;
                              ld_del_cnt_q   <= true; -- wait some clocks before Refresh
                              
                           when others =>
                              assert FALSE report "Wrong Command !" severity error;
                        end case;
                     end if;
                     
                  end if;
               
               -- in allen States nach WAIT_CMD die Adresse aus den Registern row_adr und col_adr laden
               when ST_WRITE1 =>
                  state_q <= ST_WAIT_CMD;
                  
               when WR_PRECH =>
                  sdr_if_q    <= COMMAND(PRECHARGE);
                  ld_ct_cnt_q <= true;
                  state_q     <= ST_WR_ACTIVATE;
                  a_int_q(AUTO_PRECHARGE) <= '1';  -- precharge all

               when ST_WR_ACTIVATE =>
                  if ct_cnt_q=1 then -- Counter direkt abfragen, damit min. Delay erreicht wird
                     sdr_if_q    <= COMMAND(ACTIVE);
                     a_int_q     <= row_adr_q; -- set ROW address
                     ld_ct_cnt_q <= true;
                     state_q     <= ST_WAIT_WR;
                  end if;
                  
               when ST_WAIT_WR =>
                  if ct_cnt_q=1 then
                     start_wr := true;
                     a_int_q  <= col_adr_q; -- set COL address  
                     sdr_if_q <= COMMAND(BURST_WR); -- Kommando setzen
                     state_q  <= ST_WRITE1;
                  end if;

               -- Auto Refresh
               -- Do a precharge all, followed by refresh and by an activate for last ROW
               when ST_RFSH_0 =>
                  a_int_q(AUTO_PRECHARGE) <= '1';  -- precharge all, bank-bits are don't care
                  if del0_q then
                     -- All banks must be precharged before Refresh
                     sdr_if_q     <= COMMAND(PRECHARGE);
                     ld_ct_cnt_q  <= true;
                     state_q      <= ST_RFSH_1;
                  end if;

               when ST_RFSH_1 =>
                  if ct_cnt_q=1 then
                     state_q      <= ST_RFSH_2;
                     sdr_if_q     <= COMMAND(REFRESH);
                     ld_ct_cnt_q  <= true;
                  end if;
                  
               when ST_RFSH_2 =>
                  if ct_cnt_q=1 then
                     ld_ct_cnt_q <= true;
                     a_int_q     <= row_adr_q; -- set current ROW address
                     sdr_if_q    <= COMMAND(ACTIVE);
                     -- Active to RD/WR or Active to Precharge?
                     if do_prech_q then

⌨️ 快捷键说明

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