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

📄 epp_dwidth.vhd

📁 MicroBlaze 外设,opb_epp利用pc并可与MicroBlaze进行通信
💻 VHD
字号:
-- change data width from 8-bit to 8-bit, 16-bit or 32-bit

-- by Erenst Jamro 
--//////////////////////////////////////////////////////////////////////
--//// Copyright (C) 2003 Authors                                   //// 
--////                                                              ////
--//// This source file may be used and distributed without         ////
--/// restriction provided that this copyright statement is not     ////
--//// removed from the file and that any derivative work contains  ////
--//// the original copyright notice and the associated disclaimer. ////
--////                                                              ////
--//// This source file is free software; you can redistribute it   ////
--//// and/or modify it under the terms of the GNU Lesser General   ////
--//// Public License as published by the Free Software Foundation; ////
--//// either version 2.1 of the License, or (at your option) any   ////
--//// later version.                                               ////
--////                                                              ////
--//// This source 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 Lesser General Public License for more  ////
--//// details.                                                     ////


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity epp_dwidth is
  generic(dwidth: integer:= 32;
       use_seqAddr: integer:= 1); -- assume that the read or write is sequancial
  port (clk, arst: in std_logic;
        -- common logic
        seqAddr: in std_logic; -- the next read /writes will be sequencial- use always seqAddr when transfering data unless use_seqAddr<=0
        rnw: in std_logic; -- read not write
        buf_valid: out std_logic; -- valid data write buffer - do not change the address and rnw
        -- 8-bit data interface
        adr8: in std_logic_vector(0 to 31);
        stb8: in std_logic;
        ack8: out std_logic;
        din8: in std_logic_vector(0 to 7);
        dout8: out std_logic_vector(0 to 7);
        -- dwidth data interface
        adr: out std_logic_vector(0 to 31);
        stb: out std_logic;
        ack: in std_logic;
        be: out std_logic_vector(0 to dwidth/8-1);
        din: in std_logic_vector(0 to dwidth-1);
        dout: out std_logic_vector(0 to dwidth-1));
end epp_dwidth;

architecture arch of epp_dwidth is
  constant width8: integer:= 8/dwidth; -- 1 when dwidth=8 else '0'
  signal ack8i, stbi: std_logic; -- internal ack8
  signal buf_rd: std_logic_vector(8 to dwidth-1+width8); -- internal buffer (except the MSB which is read directly)
  signal be_wr: std_logic_vector(0 to dwidth/8-2+width8); -- valid bytes is the buffer (the MSB is directly copied from din8 to dout
  signal be_rd: std_logic; -- the read buffer is valid (all Bytes exept the MSB which is read directly)
begin
  g1: if use_seqAddr>0 and dwidth>8 generate
    ack8<= ack8i;

    g16: if dwidth=16 generate
      -- write buffer for the MSB
      process(arst, clk) begin
        if arst='1' then dout(0 to 7)<= (others=>'0'); be_wr(0)<='0';
        elsif clk'event and clk='1' then
          if ack='1' then
            be_wr(0)<= '0';
          elsif ack8i='1' and rnw='0' and adr8(31)='0' then
            dout(0 to 7)<= din8;
            be_wr(0)<= '1';
          end if;
        end if;
      end process;
      dout(8 to 15)<= din8;
      -- read buffer
      process(arst, clk) begin
        if arst='1' then buf_rd<= (others=>'0'); be_rd<= '0';
        elsif clk'event and clk='1' then
          if ack='1' then
            buf_rd<= din(8 to 15);
          end if;
          if seqAddr='0' then
            be_rd<= '0'; -- not longer valid
          elsif ack='1' and rnw='1' then
            be_rd<= '1';
          elsif ack8i='1' and adr8(31)='1' then
            be_rd<='0';
          end if;
        end if;
      end process;
      dout8<= din(0 to 7) when adr8(31)='0' else buf_rd;
      stbi<= be_wr(0) when seqAddr='0' else -- finish the cycle without the full transfer or 
            '0' when stb8='0' else -- direct copy of the one byte (therefore stb8 must be '1')
            not adr8(31) or  not be_rd when rnw='1' else -- read the MSB (or the start of reading)
            adr8(31); -- write the LSB
      be(0)<= be_wr(0) when rnw='0' else -- when write
             not adr8(31); -- read
      be(1)<= '1' when rnw='1' else -- read
              adr8(31) and stb8; -- write
      ack8i<= ack when rnw='1' and adr8(31)='0' else -- direct read
              stb8 and be_rd when rnw='1' else -- read from the buffer (LSB)
              stb8 when adr8(31)='0' else -- the MSB write to buffer
              ack; -- the direck write to the LSB
      buf_valid<= be_wr(0);
      adr(0 to 30)<= adr8(0 to 30);
      adr(31)<= '0' when be_wr(0)='1' else adr8(31);
    end generate; -- dwidth=16
    
    ----------------------------------------------------------------------------------
    g32: if dwidth=32 generate
      -- write buffer (not for the LSB)
      process(arst, clk) begin
        if arst='1' then dout(0 to 23)<= (others=>'0'); be_wr(0 to 2)<="000";
        elsif clk'event and clk='1' then
          if ack='1' then
            be_wr(0 to 2)<= "000";
          elsif ack8i='1' and rnw='0' then
            if adr8(30 to 31)= "00" then
              dout(0 to 7)<= din8;
              be_wr(0)<= '1';
            elsif adr8(30 to 31)= "01" then
              dout(8 to 15)<= din8;
              be_wr(1)<= '1';
            elsif adr8(30 to 31)= "10" then
              dout(16 to 23)<= din8;
              be_wr(2)<= '1';
            end if;
          end if;
        end if;
      end process;
      dout(24 to 31)<= din8;
      -- read buffer  be_rd(1)<= the MSBs read bytes are valid 
      process(arst, clk) begin
        if arst='1' then buf_rd<= (others=>'0'); be_rd<= '0';
        elsif clk'event and clk='1' then
          if ack='1' then
            buf_rd<= din(8 to 31);
          end if;
          if seqAddr='0' then
            be_rd<= '0';
          elsif ack='1' and rnw='1' then
            be_rd<= '1';
          elsif ack8i='1' and adr8(30 to 31)="11" then -- the last read
            be_rd<='0';
          end if;
        end if;
      end process;
      dout8<= din(0 to 7) when adr8(30 to 31)="00"  else 
             buf_rd(8 to 15) when adr8(30 to 31)="01"  else 
             buf_rd(16 to 23) when adr8(30 to 31)="10"  else 
             buf_rd(24 to 31);
      stbi<= be_wr(0) or be_wr(1) or be_wr(2) when seqAddr='0' else -- finish the cycle without the full transfer or 
            '0' when stb8='0' else -- direct copy of the one byte (therefore stb8 must be '1')
            ( (not adr8(30)) and (not adr8(31))) or not be_rd when rnw='1' else -- read the MSB or the start of reading
            '1' when adr8(30 to 31)= "11" else '0'; -- write the LSB
      be(0)<= be_wr(0) when rnw='0' else -- when write
             '1' when adr8(30 to 31)="00" else '0'; -- read
      be(1)<= be_wr(1) when rnw='0' else -- when write
             '1' when adr8(30)='0' else '0'; -- read
      be(2)<= be_wr(2) when rnw='0' else -- when write
             '1' when adr8(30 to 31)/="11" else '0'; -- read
      be(3)<= '1' when rnw='1' else -- read
              '1' when adr8(30 to 31)="11" else '0'; -- direct write
      ack8i<= ack when rnw='1' and adr8(30 to 31)="00" else -- direct read
              stb8 and be_rd when rnw='1' else -- read from the buffer (3 LSBs)
              stb8 when adr8(30 to 31)/="11" else -- (not the LSB) write to buffer
              ack; -- the direct write to the LSB
      buf_valid<= be_wr(0) or be_wr(1) or be_wr(2);
      adr(0 to 29)<= adr8(0 to 29);
      adr(30 to 31)<= "00" when be_wr(0)='1' else
                      "01" when be_wr(1)='1' else
                      "10" when be_wr(1)='1' else
                      adr8(30 to 31);
   end generate;
 end generate; 

--------------------------------------------------------------------------------------------------------------
  g0: if use_seqAddr<=0 and dwidth>8 generate -- combinational logic
    stbi<= stb8;
    ack8<= ack;
    buf_valid<= '0';
    adr<= adr8;
    g16: if dwidth=16 generate
      dout(0 to 7)<= din8;
      dout(8 to 15)<= din8;
      dout8<= din(0 to 7) when adr8(31)='0' else din(8 to 15);
      be(0)<= not adr8(31);
      be(1)<= adr8(31);
    end generate;
    
    g32: if dwidth=32 generate
      dout(0 to 7)<= din8;
      dout(8 to 15)<= din8;   
      dout(16 to 23)<= din8;
      dout(24 to 31)<= din8;
      dout8<= din(0 to 7) when adr8(30 to 31)="00" else 
              din(8 to 15) when adr8(30 to 31)="01" else
              din(16 to 23) when adr8(30 to 31)="10" else
              din(24 to 31);
      be(0)<= '1' when adr8(30 to 31)="00" else '0';
      be(1)<= '1' when adr8(30 to 31)="01" else '0';
      be(2)<= '1' when adr8(30 to 31)="10" else '0';
      be(3)<= '1' when adr8(30 to 31)="11" else '0';
    end generate;
  end generate;
  
  -- direct copy
  g8: if dwidth=8 generate
    stbi<= stb8;
    ack8<= ack;
    adr<= adr8;
    buf_valid<= '0';
    dout(0 to 7)<= din8;
    dout8<= din;
    be(0)<= '1';
  end generate;
    
  -- Additional flip-flop on stbi to reduce delay path
  process(clk, arst) begin
    if arst='1' then stb<='0';
    elsif clk'event and clk='1' then
      stb<= stbi and not ack;
    end if;
  end process;
end arch;
    

⌨️ 快捷键说明

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