-- -- Transition Radiation Detector -- -- MCM Control Unit - Configuration Network -- -- -- -- $Id$ -- -- Robin Gareus, Kirchhoff Institute for Physics, Heidelberg -- rgareus@kip.uni-heidelberg.de -- ------------------------------------------------------------ -- -- Output Buffer -- -- This is the data buffer for outgoing data. -- data may be written in paralell. (all 68 bits) using the -- data_in,data_we signals when the buffer is write enabled (not frozen) -- signaled by 'buffer_ready'. -- -- in frozen state (freeze_in = '1'). the buffered data can be read once(!) -- serialized with a 16bit CRC checksum added. -- After entering frozen state, the first bit to send is put out on 'data_out'. -- To request the next bit, set 'request_in' to '1'. -- -- while shifting the buffer, a CRC checksum is computed, that is appended -- to the data. When data and checksum have been strobed out, with the last bit -- being set on 'data_out' the buffer_empty flag is set to '1'. -- -- Generics: -- BUFSIZ : number of data bits to be stored in the buffer -- COUNTER : # of bits needed for the bitcounter -- The bitcounter has to count from 0 to (BUFSIZ+CRCLEN) -- -- CRCLEN as well as the CRC_POLY are no generic values, but CONSTANTS -- to be defined in the header of the architecture. -------------------------------------------------- -- standard includes, library definitions. -------------------------------------------------- library ieee,work; use ieee.std_logic_1164.all; use IEEE.std_logic_unsigned.all; -------------------------------------------------- -- ENTITY -------------------------------------------------- entity mcm_nw_outbuf is generic ( BUFSIZ : integer := 69; -- size of buffer COUNTER : integer := 7 -- # of bits needed to count (BUFSIZ+CRCLEN) ); port( -- Signals to (sendtiming/stuffing) in DLL request_in : in std_logic; -- shift buffer, set data_out, freeze_in : in std_logic; -- disable write_enable, allow shifts data_out : out std_logic; -- just what it says buffer_empty : out std_logic; -- no more data to shift in buffer -- Signals to upper layer data_in : in std_logic_vector (BUFSIZ-1 DOWNTO 0); buffer_ready : out std_logic; -- data_in may be written. data_we : in std_logic; -- written data is now valid. -- clock and reset clk_buf : in std_logic; clk : in std_logic; reset_n : in std_logic ); end mcm_nw_outbuf; -------------------------------------------------- -- ARCHITECTURE -------------------------------------------------- architecture structural of mcm_nw_outbuf is CONSTANT CRCLEN : integer := 16; CONSTANT CRC_POLY: std_logic_vector(CRCLEN-1 DOWNTO 0) := "1000000000000101"; SIGNAL bitcounter : std_logic_vector (COUNTER-1 DOWNTO 0); SIGNAL ob_data : std_logic_vector (BUFSIZ-1 DOWNTO 0); SIGNAL ob_crc : std_logic_vector (CRCLEN-1 DOWNTO 0); SIGNAL ob_empty : std_logic; SIGNAL crc_empty : std_logic; begin -- depending on remaining bits in buffer, set output to buffer or crc. output_data: process( ob_empty,ob_data,ob_crc) begin if (ob_empty = '0') then data_out <= ob_data(BUFSIZ-1); else data_out <= ob_crc(CRCLEN-1); end if; end process output_data; -- this process does everything :) -- data is written, shifted and crc is calculated. shift_n_crc: process(reset_n,clk_buf) begin if (reset_n = '0') then -- async reset. ob_data <= (OTHERS => '0'); ob_crc <= (OTHERS => '0'); elsif(clk_buf'event and clk_buf = '1') then if ( freeze_in = '0' and data_we = '1') then ob_data <= data_in; -- write is done here... also prepare for CRC: ob_crc(CRCLEN-1 DOWNTO 0)<=data_in(BUFSIZ-1 DOWNTO (BUFSIZ-CRCLEN)); elsif ( freeze_in = '1' and request_in = '1') then -- shift buffer if ( crc_empty = '0') then -- still data to send left. ob_data(BUFSIZ-1 DOWNTO 1) <= ob_data(BUFSIZ-2 DOWNTO 0); ob_data(0)<='0'; -- this is needed for CRC. if ( ob_crc(CRCLEN-1) = '1' and ob_empty = '0' ) then ob_crc(CRCLEN-1 DOWNTO 1) <= -- CRC calculation is done here. ob_crc(CRCLEN-2 DOWNTO 0) xor CRC_POLY(CRCLEN-1 DOWNTO 1); ob_crc(0)<= ( ob_data(BUFSIZ-CRCLEN-1) xor CRC_POLY(0)); else ob_crc(CRCLEN-1 DOWNTO 1) <= ob_crc(CRCLEN-2 DOWNTO 0); ob_crc(0)<=ob_data(BUFSIZ-CRCLEN-1); end if; end if; end if; end if; end process shift_n_crc; -- simple counter to keep track, how many bits have already been shifted. count: process(clk,freeze_in,reset_n) begin if ( reset_n = '0') then bitcounter <= (others => '0'); elsif (clk'event and clk = '1' ) then if (freeze_in = '0') then bitcounter <= (others => '0'); elsif (request_in = '1' and crc_empty = '0') then bitcounter <= bitcounter + '1'; end if; end if; end process count; -- depending on the counter value: set some status flags: -- crc_empty: CRC-buffer is empty -- ob_empty: data-buffer is empty stateflags: process(bitcounter) begin if (bitcounter >= (BUFSIZ+CRCLEN) ) then crc_empty <= '1'; else crc_empty <= '0'; end if; if (bitcounter >= BUFSIZ ) then ob_empty <= '1'; else ob_empty <= '0'; end if; end process stateflags; buffer_empty <= crc_empty ; buffer_ready <= not freeze_in; end structural; -------------------------- -- CONFIGURATION -------------------------- -- synopsys translate_off configuration mcm_nw_outbuf_CFG of mcm_nw_outbuf is for structural end for; end mcm_nw_outbuf_CFG; -- synopsys translate_on