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

📄 top_vhd.vhd

📁 VHDL设计实例
💻 VHD
字号:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

library WORK1;
use WORK1.SER_PAR_LIB.all;

--
--
-- Serial to Parallel Convertor
--
-- This module takes multiple serial data streams, which are bit-synchronous with each other,
-- and converts the data to a parallel words.
--
-- Several constants are declared in the WORK1.SER_PAR_LIB library, including the number of serial ports
-- to be converted and ENABLE_WRITE_STALL and ENABLE_READ_STALL. The user must determine the input bit rate
-- the output bit rate and the appropriate side to stall when one side cannot keep up with the other.
--
-- The design takes heavy use of Virtex's LUT based shift registers and Distributed Dual Port RAM.
--
-- The Dual Port Rams are used to double buffer the incomming data, as well as parallelize the data.
-- Data is written into one half of the memory, in a bit-wise fasion, while it is read out of the other
-- half of the memory in a parallel fashion.  A ping-ponging of the memory occurs as one half emptys and 
-- the other half fills, with the end result being that the reads now occur in the half just written, and 
-- the writes now occur in the half just read.  It takes 32 Slices, or 16 CLBs to store and double buffer 
-- 8 channels of 32 bit data. Using a traditional shift register-latch approach would require (8 * 32 * 2 =) 512
-- flip flops, which is 256 slices or 128 CLBs.  Some of this savings is lost due to some additional over-
-- head.  
--
-- The Shift Register LUTs are used to create effient delay lines which are used to create time-skewed
-- versions of the input data, such that an 8-bit word is available for writting into the dual port memories.
-- The incomming data is arranged into groups of 8, which then run through a delay line structure, is steered
-- by eight 8 to one muxes, and then flows into the dual-port memory structure discused above.
--
-- Each port position in each group of eight has a different delay, from 0 to seven clocks.  Thus at any
-- given time, a different bit-number is available from each port.  For example, assuming port 0 has a delay
-- of zero, port 1 has a delay of one, and so on.  After seven clocks, the data at the output of the port 0 delay
-- line is bit 7, whereas the data at the output of the port 1 delay line is bit 6, down to bit 0 available at
-- port 7.  The dual ports are arranged so that each dual port holds all the bit N's for all of the 8 channels.
-- Thus with the data skewed, we can write to 8 dual ports simultaneously. The delay lines require a total of 8
-- LUTs, or 4 slices which translates into 2 CLBS per 8 channels.
--

entity TOP_VHD is
	generic(NUMBER_OF_SERIAL_PORTS: INTEGER := PORTS);
	port(
	    SERIAL_DATA : in STD_LOGIC_VECTOR (NUMBER_OF_SERIAL_PORTS-1 downto 0);
	    WRITE_ENABLE_IN : in STD_LOGIC;
	    WCLK : in STD_LOGIC;
	    RCLK : in STD_LOGIC;
	    RESET : in STD_LOGIC;
	    WRITE_ENABLE_OUT : out STD_LOGIC;
	    READ_ENABLE_OUT : out STD_LOGIC;
	    READ_COUNT_OUT : out INTEGER;
	    INCREMENT_BCOUNT : out STD_LOGIC;
	    DECREMENT_BCOUNT : out STD_LOGIC;
	    DATA : out STD_LOGIC_VECTOR (31 downto 0)
	    );
end TOP_VHD;
--
architecture TOP_VHD_arch of TOP_VHD is
--
-- The S2P8X32 module (Serial to Parallel convertor, 8 channels by 32 bit).  This module
-- takes eight serial input streams and outputs eight 32 bit words. It consists of a delay
-- module, eight 8X1 muxes, and thirty-two 16X1 dual-port RAMS.
--
component S2P8X32
    port (
        SERIAL_DATA: in STD_LOGIC_VECTOR(7 downto 0);
        WRITE_ENABLE: in STD_LOGIC;
        WR_CLK: in STD_LOGIC;
        WRITE_ADDRESS: in WRITE_ADDRESS_ARRAY;
        MSB_WR: in STD_LOGIC_VECTOR(3 downto 0);
        DP_WR_EN: in STD_LOGIC_VECTOR(31 downto 0);
        RESET: in STD_LOGIC;
        OE: in STD_LOGIC;
        RD_CLK: in STD_LOGIC;
        READ_ENABLE: in STD_LOGIC;
        FORCE_RD_ADDRESS_INC: in STD_LOGIC;
	ADJUST_ADDRESS_MASK: in STD_LOGIC;
        DATA_BANK_OUT: out STD_LOGIC_VECTOR(31 downto 0)
    );
end component;
--
-- Write Control Logic - Consists of eight 3-bit, that count synchronously, with the counter
-- that drives WADDR_A initializes to 0 at reset, WADDR_B initializes to 7, C to 6, etc. It also
-- contains a 32-bit one-hot state-machine, which is just a 32 bit shift register, that initializes
-- to FE000001 on reset.
--
component WR_CNTRL
    port (
	DP_WR_EN : out STD_LOGIC_VECTOR (31 downto 0);
	WA_MSB : out STD_LOGIC_VECTOR (3 downto 0);
	WRITE_ADDRESS : out WRITE_ADDRESS_ARRAY;
	INCREMENT_BCOUNT: out STD_LOGIC;
	CLK : in STD_LOGIC;
	RESET : in STD_LOGIC;
	WRITE_ENABLE : in STD_LOGIC
    );
end component;
--
-- Global clock buffer for read and write clock.....may want to change to DLL
--
component BUFG
    port (
	I : in STD_LOGIC;
	O : out STD_LOGIC
    );
end component;
--
--
--
component RD_CNTRL
    generic(
	NUMBER_OF_BANKS: INTEGER;
	NUMBER_OF_SERIAL_PORTS: INTEGER
    );
    port (
        RESET: in STD_LOGIC;
        CLK: in STD_LOGIC;
        READ_ENABLE: in STD_LOGIC;
        READ_COUNT_OUT: out INTEGER;
        DECREMENT_BCOUNT: out STD_LOGIC;
        FORCE_RD_ADDRESS_INC: out STD_LOGIC;
        OE: out STD_LOGIC_VECTOR (NUMBER_OF_BANKS-1 downto 0)                
    );
end component;
--
--
--
component SYNC
    generic(
        ENABLE_READ_STALL:INTEGER;
        ENABLE_WRITE_STALL:INTEGER
    );
    port (
        RESET: in STD_LOGIC;
        RD_CLK: in STD_LOGIC;
        WR_CLK: in STD_LOGIC;
        DECREMENT_BCOUNT: in STD_LOGIC;
        INCREMENT_BCOUNT: in STD_LOGIC;
        ENABLE_IN: in STD_LOGIC;
        WRITE_ENABLE: out STD_LOGIC;
        READ_ENABLE: out STD_LOGIC
    );
end component;
--
-- Pipe line stage for output data
--
component OUTPUT_PIPELINE
    generic(
        NUMBER_OF_BANKS: INTEGER;
        NUMBER_OF_STAGES: INTEGER
        );
    port (
        DATA_IN:in DATA_OUT_ARRAY;
        RD_CLK: in STD_LOGIC;
        READ_ENABLE: in STD_LOGIC;
        READ_ENABLE_OUT: out STD_LOGIC;
        DATA_OUT: out STD_LOGIC_VECTOR (31 downto 0)
    );
end component;
--
--CONSTANT Declarations
--
constant NUMBER_OF_BANKS: INTEGER := BANKS;
constant ADDRESS_ADJUST_MASK: STD_LOGIC_VECTOR(BANKS-1 downto 0):= MASK;
constant NUMBER_OF_STAGES: INTEGER:= STAGES;
--
-- Interconnect signals
--
signal RD_CLK : STD_LOGIC;
signal WR_CLK : STD_LOGIC;
signal WRITE_ADDRESS : WRITE_ADDRESS_ARRAY;
signal DP_WR_EN : STD_LOGIC_VECTOR (31 downto 0);
signal WA_MSB : STD_LOGIC_VECTOR (3 downto 0);
signal OE : STD_LOGIC_VECTOR ((NUMBER_OF_BANKS-1) downto 0);
signal DECREMENT_BCOUNT_INT : STD_LOGIC;
signal INCREMENT_BCOUNT_INT : STD_LOGIC;
signal READ_ENABLE : STD_LOGIC;
signal WRITE_ENABLE : STD_LOGIC;
--
-- Setup array, so that inputs can be split up into N 8-bit vectors
--
signal SERIAL_DATA_VECTORS: SERIAL_DATA_ARRAY;

signal TEMP_ADDRESS_ADJUST_MASK: STD_LOGIC_VECTOR(NUMBER_OF_BANKS-1 downto 0);

signal FORCE_RD_ADDRESS_INC : STD_LOGIC;

signal DATA_ARRAY : DATA_OUT_ARRAY;

signal DATA_BANK : STD_LOGIC_VECTOR (31 downto 0);

begin

WRITE_ENABLE_OUT <= WRITE_ENABLE;
INCREMENT_BCOUNT <= INCREMENT_BCOUNT_INT;
DECREMENT_BCOUNT <= DECREMENT_BCOUNT_INT;	    
TEMP_ADDRESS_ADJUST_MASK <= ADDRESS_ADJUST_MASK;
--
-- Organize serial data into vectors
--
--CREATE_SERIAL_DATA_ARRAY(SERIAL_DATA,SERIAL_DATA_VECTORS);
--
--
-- Create serial data array, scattering the data so that adjacent channels end up in adjacent banks
--
process(SERIAL_DATA)
    procedure CREATE_SERIAL_DATA_ARRAY
        (signal SERIAL_DATA:in STD_LOGIC_VECTOR(PORTS-1 downto 0);
   	 signal SERIAL_DATA_VECTORS: out SERIAL_DATA_ARRAY
        ) is
        variable TEMP:STD_LOGIC_VECTOR((8*BANKS)-1 downto 0);
    begin
        if ((PORTS mod 8)=0) then
            TEMP := SERIAL_DATA;
        else
            TEMP(PORTS-1 downto 0) :=SERIAL_DATA;
            for I in (8*BANKS)-1 to PORTS loop
                TEMP(I) := '0';
            end loop;
        end if;        
        for I in 0 to (BANKS-1) loop
            for J in 0 to 7 loop
                SERIAL_DATA_VECTORS(I)(J) <= TEMP((J*BANKS)+I);
            end loop;
        end loop;
     end procedure CREATE_SERIAL_DATA_ARRAY;
begin
    CREATE_SERIAL_DATA_ARRAY(SERIAL_DATA,SERIAL_DATA_VECTORS);
end process;     
--
--COMPONENT INSTANCES
--
--
-- The S2P8X32 module (Serial to Parallel convertor, 8 channels by 32 bit).  This module
-- takes eight serial input streams and outputs eight 32 bit words. It consists of a delay
-- module, eight 8X1 muxes, and thirty-two 16X1 dual-port RAMS.
--
-- The serial data is "Scattered" so that adjacent channels end up in adjacent banks of the
-- convertor. This ensures that the first N channels are available first for output.
--
CONVERTOR1:
for I in 0 to (NUMBER_OF_BANKS-1) generate
   CONV1: S2P8X32
   port map (
	SERIAL_DATA => SERIAL_DATA_VECTORS(I),
	WRITE_ADDRESS => WRITE_ADDRESS,
	DP_WR_EN => DP_WR_EN,
	MSB_WR => WA_MSB,
	OE => OE(I),
	DATA_BANK_OUT => DATA_ARRAY(I)(31 downto 0),
	ADJUST_ADDRESS_MASK => TEMP_ADDRESS_ADJUST_MASK(I),
	WR_CLK => WR_CLK,
	WRITE_ENABLE => WRITE_ENABLE,
        FORCE_RD_ADDRESS_INC => FORCE_RD_ADDRESS_INC,
	RESET => RESET,
	READ_ENABLE => READ_ENABLE,
	RD_CLK => RD_CLK
	);
end generate;
--
-- Write Control Logic - Consists of eight 3-bit, that count synchronously, with the counter
-- that drives WADDR_A initializes to 7 at reset, WADDR_B initializes to 0, C to 1, etc. It also
-- contains a 32-bit one-hot state-machine, which is just a 32 bit shift register, that initializes
-- to FE000001 on reset.
--
WRITE_CNTRL1 : WR_CNTRL port map(
	DP_WR_EN => DP_WR_EN,
	WA_MSB => WA_MSB,
	WRITE_ADDRESS => WRITE_ADDRESS,
	INCREMENT_BCOUNT => INCREMENT_BCOUNT_INT,
	CLK => WR_CLK,
	RESET => RESET,
	WRITE_ENABLE => WRITE_ENABLE
);
--
-- Global clock buffer for read clock.....may want to change to DLL
--
GLOBAL_RCLK1 : BUFG port map(
	I => RCLK,
	O => RD_CLK
);
--
-- Global clock buffer for write clock.....may want to change to DLL
--
GLOBAL_WCLK1 : BUFG port map(
	I => WCLK,
	O => WR_CLK
);
--
--
--
READ_CTRL1 : RD_CNTRL generic map(
	NUMBER_OF_BANKS => NUMBER_OF_BANKS,
	NUMBER_OF_SERIAL_PORTS => NUMBER_OF_SERIAL_PORTS
	)
	port map(
	RESET => RESET,
	CLK => RD_CLK,	
	READ_ENABLE => READ_ENABLE,
	READ_COUNT_OUT => READ_COUNT_OUT,
	DECREMENT_BCOUNT => DECREMENT_BCOUNT_INT,
        FORCE_RD_ADDRESS_INC => FORCE_RD_ADDRESS_INC,
	OE => OE
);
--
--
--
SYNC1 : SYNC generic map(
        ENABLE_READ_STALL => ENABLE_READ_STALL,
        ENABLE_WRITE_STALL => ENABLE_WRITE_STALL
	)
        port map(
        RESET => RESET,
        RD_CLK => RD_CLK,
        WR_CLK => WR_CLK,
        DECREMENT_BCOUNT => DECREMENT_BCOUNT_INT,
        INCREMENT_BCOUNT => INCREMENT_BCOUNT_INT,
        ENABLE_IN => WRITE_ENABLE_IN,
        WRITE_ENABLE => WRITE_ENABLE,
        READ_ENABLE => READ_ENABLE
);
--
-- PIPELINE DATA OUT
--
OUTPIPE1 : OUTPUT_PIPELINE
    generic map(
        NUMBER_OF_BANKS=> NUMBER_OF_BANKS,
        NUMBER_OF_STAGES=> NUMBER_OF_STAGES
        )
    port map(
        DATA_IN => DATA_ARRAY,
        READ_ENABLE => READ_ENABLE,
        READ_ENABLE_OUT => READ_ENABLE_OUT,
        RD_CLK => RD_CLK,
        DATA_OUT => DATA
    );


end TOP_VHD_arch;

⌨️ 快捷键说明

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