📄 top_vhd.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 + -