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

📄 ahb_slv.vhd

📁 free hardware ip core about sparcv8,a soc cpu in vhdl
💻 VHD
📖 第 1 页 / 共 2 页
字号:
--------------------------------------------------------------------------------  This file is a part of the GRLIB VHDL IP LIBRARY--  Copyright (C) 2003, Gaisler Research----  This program is free software; you can redistribute it and/or modify--  it under the terms of the GNU General Public License as published by--  the Free Software Foundation; either version 2 of the License, or--  (at your option) any later version.----  This program is distributed in the hope that it will be useful,--  but WITHOUT ANY WARRANTY; without even the implied warranty of--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the--  GNU General Public License for more details.----  You should have received a copy of the GNU General Public License--  along with this program; if not, write to the Free Software--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA ------------------------------------------------------------------------------- Entity:      ahb_slv-- File:        ahb_slv.vhd-- Author:      David Lindh - Gaisler Research-- Description: AMBA AHB slave interface for DDR-RAM memory controller------------------------------------------------------------------------------library ieee;use ieee.std_logic_1164.all;library grlib;use grlib.amba.all;use grlib.stdlib.all;library gaisler;use grlib.devices.all;use gaisler.memctrl.all;library techmap;use techmap.gencomp.all;use techmap.allmem.all;use gaisler.ddrrec.all;entity ahb_slv is  generic (    hindex      :     integer := 0;    haddr       :     integer := 0;    hmask       :     integer := 16#f80#;    sepclk      :     integer := 0;    dqsize      :     integer := 64;    dmsize      :     integer := 8;    tech        :     integer := virtex2);  port (    rst      : in  std_ulogic;    hclk     : in  std_ulogic;    clk0     : in  std_ulogic;    csi      : in  ahb_ctrl_in_type;    cso      : out ahb_ctrl_out_type);end ahb_slv;architecture rtl of ahb_slv is  -- Configuration for AMBA PlugNplay  constant REVISION : integer         := 0;  constant HCONFIG  : ahb_config_type := (    0      => ahb_device_reg ( VENDOR_GAISLER, GAISLER_DDRMP, 0, REVISION, 0),    4      => ahb_membar(haddr, '1', '1', hmask),    others => zero32);  type burst_mask_type is array (buffersize-1 downto 0) of integer range 1 to 8;  type hsize_type is array (4 downto 0) of integer range 8 to 128;  constant hsize_array : hsize_type := (128, 64, 32, 16, 8);    signal ahbr       : ahb_reg_type;  signal ahbri      : ahb_reg_type;  signal csi_synced : ahb_ctrl_in_type;  signal DSRAM_i    : syncram_dp_in_type;  signal DSRAM_o    : syncram_dp_out_type;  signal ASRAM_i    : syncram_2p_in_type;  signal ASRAM_o    : syncram_2p_out_type;  signal vcc        : std_ulogic;  begin  -- rtl   vcc <= '1'; -------------------------------------------------------------------------------   --AMBA AHB control combinatiorial part -------------------------------------------------------------------------------    ahbcomb : process(ahbr, rst, csi, csi_synced, DSRAM_o)        variable v : ahb_reg_type;          -- local variables for registers    variable next_rw_cmd_valid : std_logic_vector((log2(buffersize)-1) downto 0);  begin    v                 := ahbr;    next_rw_cmd_valid := v.rw_cmd_valid +1;    v.new_burst := '0';    v.sync_write := '0';    v.sync2_write := '0';      -------------------------------------------------------------------------------     -- Give respons on prevoius address cycle  (DATA CYCLE) -------------------------------------------------------------------------------            -- If read and read prediction in previos cycle. Both couldn't be    -- written into address syncram (sync2)    if ahbr.sync2_busy = '1' then      v.sync2_adr   := v.pre_read_buffer;      v.sync2_wdata := '0' & ahbr.pre_read_adr;      v.sync2_write := '1';      v.sync2_busy  := '0';    end if;                                  -- In case of a write followed by a read both will try to use sync_ram     -- in same cycle, delays read.    if ahbr.sync_busy = '1' then      v.sync_adr    := ahbr.sync_busy_adr;      v.doRead      := '1';                      -- Write data to address given in previous cycle    elsif ahbr.doWrite = '1' then         -- If first word set all datamasks      if conv_std_logic_vector(v.writecounter,4)(0) = '0' then        v.sync_wdata((2*(dmsize+dqsize))-1 downto 2*dqsize) :=  (others => '1');      end if;                -- Write data to syncram      v.even_odd_write := (conv_integer(conv_std_logic_vector(v.writecounter,4)(0)));      for i in 0 to dqsize-1 loop        if i >= v.startp*8  and i < (v.startp+v.burst_hsize)*8  then          v.sync_wdata(i + v.even_odd_write*dqsize) := csi.ahbsi.hwdata(i+(v.ahbstartp-v.startp)*8);        end if;      end loop;      -- Clear masks for valid bytes      for i in 0 to dmsize-1 loop        if i >= v.startp and i < (v.startp+v.burst_hsize) then           v.sync_wdata((2*dqsize)+v.even_odd_write*dmsize+i) := '0';        end if;      end loop;      v.sync_adr    := v.use_write_buffer & conv_std_logic_vector(v.writecounter,4)(2 downto 1);      v.sync_write  := '1';      -- Increase mask counter      v.burst_dm(conv_integer(v.use_write_buffer)) := v.writecounter+1;       v.doWrite            := '0';    end if;          -------------------------------------------------------------------------------    -- Analyze incomming command on AHB   (ADDRESS CYCLE)-------------------------------------------------------------------------------    v.sync_busy   := '0';        -- An error occured in previous address cycle    if ahbr.prev_error = '1' then      v.hresp := HRESP_ERROR;      v.hready := '1';      v.prev_retry := '0';      v.prev_error := '0';            -- A retry occured in previous address cycle    elsif ahbr.prev_retry = '1' then      v.hresp := HRESP_RETRY;      v.hready := '1';      v.prev_retry := '0';      v.prev_error := '0';            -- Slave selected and previous transfer complete    elsif csi.ahbsi.hsel(hindex) = '1' and csi.ahbsi.hready = '1' then      v.prev_retry := '0';      v.prev_error := '0';                            -- Check if hsize is within range      if hsize_array(conv_integer(csi.ahbsi.hsize)) > dqsize and csi.ahbsi.htrans(1) = '1' then        assert false report "AHB HSIZE cannot be greater then DQ size" severity error;        v.hresp := HRESP_ERROR;        v.hready := '0';        v.prev_error := '1';                          -- BUSY or IDLE command      elsif csi.ahbsi.htrans(1) = '0' then        v.hresp  := HRESP_OKAY;        v.hready := '1';                -- If idle, begin write burst (if waiting)        if csi.ahbsi.htrans = HTRANS_IDLE then          v.w_data_valid := v.rw_cmd_valid;          v.pre_read_valid := '0';        end if;                -- SEQ or NONSEQ command      else        -- Calculate valid bits for transfer according to big endian        case ahbdata is          when 8 =>  v.ahboffset := "000";          when 16 => v.ahboffset := "00" & csi.ahbsi.haddr(0);          when 32 => v.ahboffset := "0" & csi.ahbsi.haddr(1 downto 0);          when 64 => v.ahboffset := csi.ahbsi.haddr(2 downto 0);          when others => null;        end case;                        case dqsize is          when 8  => v.rwadrbuffer  := csi.ahbsi.haddr;                     v.offset       := "000";          when 16 => v.rwadrbuffer  := "0" & csi.ahbsi.haddr(31 downto 1);                     v.offset       := "00" & csi.ahbsi.haddr(0);          when 32 => v.rwadrbuffer  := "00" & csi.ahbsi.haddr(31 downto 2);                     v.offset       := "0" & csi.ahbsi.haddr(1 downto 0);          when 64 => v.rwadrbuffer  := "000" & csi.ahbsi.haddr(31 downto 3);                     v.offset       := csi.ahbsi.haddr(2 downto 0);          when others => null;        end case;                       case csi.ahbsi.hsize is          when "000" => v.burst_hsize:= 1;                        v.startp:= ((dqsize-8)/8) - conv_integer(v.offset);                        v.ahbstartp := ((ahbdata-8)/8) - conv_integer(v.ahboffset);          when "001" => v.burst_hsize:= 2; v.offset(0):= '0';                        v.startp:= ((dqsize-16)/8) - conv_integer(v.offset);                        v.ahbstartp:= ((ahbdata-16)/8) - conv_integer(v.ahboffset);          when "010" => v.burst_hsize:= 4; v.offset(1 downto 0) := "00";                        v.startp:= ((dqsize-32)/8) - conv_integer(v.offset);                        v.ahbstartp:= ((ahbdata-32)/8) - conv_integer(v.ahboffset);          when "011" => v.burst_hsize:= 8; v.offset(2 downto 0) := "000";                        v.startp:= 0;                        v.ahbstartp := 0;          when others =>            assert false report "Too large HSIZE" severity error;            v.hresp := HRESP_ERROR;            v.hready := '0';            v.prev_error := '1';        end case;      ------------------------------------------------------------------------------- -- SEQUENCIAL, continuation of burst             -- Read (seq)      if (csi.ahbsi.hwrite = '0' and csi.ahbsi.htrans = HTRANS_SEQ and          csi.ahbsi.hburst = HBURST_INCR and v.offset /= "000") then           -- Do nothing, requested data is in the same ahb word as        -- already is on ahb bus              elsif (csi.ahbsi.hwrite = '0' and csi.ahbsi.htrans = HTRANS_SEQ and             csi.ahbsi.hburst = HBURST_INCR)      then        -- Check that new command can be part of current burst        if v.readcounter /= v.blockburstlength then          -- Read from Syncram          v.sync_write  := '0';          v.doRead      := '1';        else          if csi_synced.locked = '0' then                       -- Check if a prediction was made that matches this new address            if v.pre_read_valid = '1' then              v.use_read_buffer := v.pre_read_buffer;              v.readcounter := 0;              v.blockburstlength := csi_synced.burstlength;              -- Read from Syncram              v.sync_write  := '0';              v.doRead      := '1';              v.pre_read_valid := '0';                                  -- Make new read prediction if buffer not full              if (v.pre_read_buffer+1) /= csi_synced.rw_cmd_done and csi_synced.r_predict = '1' then                v.pre_read_adr     := v.rwadrbuffer + csi_synced.burstlength;                                 v.pre_read_buffer  := v.pre_read_buffer +1;                v.pre_read_valid   := '1';                v.sync2_write      := '1';                v.sync2_wdata      := '0' & v.pre_read_adr;                v.sync2_adr        := v.pre_read_buffer;                                                                                              v.rw_cmd_valid     := v.pre_read_buffer;                v.w_data_valid     := v.pre_read_buffer;              end if;                                    -- No prediction was made, treat as non sequencial            else              v.new_burst := '1';            end if;          else            v.new_burst := '1';          end if;        end if;                  -- Write (seq)       elsif csi.ahbsi.hwrite = '1' and csi.ahbsi.htrans = HTRANS_SEQ then        v.pre_read_valid := '0';                         -- Check that new command can be part of current burst        if v.offset /= "000" then          v.doWrite := '1';          v.hresp              := HRESP_OKAY;          v.hready             := '1';        elsif v.writecounter+1 /= v.blockburstlength and csi_synced.locked = '0' then          v.writecounter := v.writecounter +1;          v.doWrite := '1';          v.hresp              := HRESP_OKAY;          v.hready             := '1';          -- Command has to start new burst        else          v.w_data_valid := v.rw_cmd_valid;          v.rw_cmd_valid := v.use_write_buffer;          v.new_burst := '1';        end if;      end if;

⌨️ 快捷键说明

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