-- CBBR: CBB Receiver of TLMU Data -- -- Addr 0: R/W write 0/1 disable/enable receiver, read status -- Addr 1: R/W: packetcounter, 32 bit, write anything to reset -- Addr 2: R/W: CRC-errorcounter, 32 bit, write anything to reset library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_UNSIGNED.all; library UNISIM; use UNISIM.vcomponents.all; entity cbbr_top is generic ( clkratio : integer := 10); -- Ratio clk40/bitclk 2=20MHz input bitrate, 1 is possible port ( clk40 : in std_logic; reset_n : in std_logic; address : in std_logic_vector(3 downto 0); -- SCSN control cbbr_IBO : in std_logic_vector(31 downto 0); -- SSCN control cbbr_OBI : out std_logic_vector(31 downto 0); -- SCSN control we : in std_logic; -- SCSN control ack : out std_logic; -- SCSN control req : in std_logic; -- SCSN control din : in std_logic_vector(7 downto 0); -- Data in do : out std_logic_vector(31 downto 0); -- Data out do_strobe : out std_logic); -- Data out strobe end cbbr_top; architecture behv of cbbr_top is component cbbr_iserdes port ( clk40 : in std_logic; reset_n : in std_logic; di : in std_logic; enable : in std_logic; dout : out std_logic_vector(3 downto 0)); end component; component ucrc_par generic ( POLYNOMIAL : std_logic_vector; INIT_VALUE : std_logic_vector; DATA_WIDTH : integer range 2 to 256; SYNC_RESET : integer range 0 to 1); port ( clk_i : in std_logic; rst_i : in std_logic; clken_i : in std_logic; data_i : in std_logic_vector(DATA_WIDTH - 1 downto 0); match_o : out std_logic; crc_o : out std_logic_vector(POLYNOMIAL'length - 1 downto 0)); end component; -- THe number of bit transmitted in one packet constant parw : integer := 704; constant numwords : integer := parw/32; -- input stage signal din_syn : std_logic_vector(7 downto 0); -- sync data inout signal din_del1 : std_logic_vector(7 downto 0); -- delay data input by 1 clk40 -- clkdiv counter to be synced with data in rate signal sample_cnt : integer range 0 to clkratio; -- bitcounter for 4:1 signal bitcnt : integer range 0 to 3; -- receiving bit signals active receiving, not set=waiting for sync on SOF signal receiving : std_logic; -- If all Data is received packet_done is rised signal packet_done : std_logic; -- Samplepoint is 1 when data can be fetched, normally at end of bittime signal samplepoint : std_logic; -- Datavalid, all 8x4 data is now valid signal datavalid : std_logic; -- Received Data after 4 shift cycles, output of sfrs signal recdata : std_logic_vector(31 downto 0); -- Received Data storage, to test timing of datavalid flag signal recdatamem : std_logic_vector(31 downto 0); -- recdatavalid signals to upper layer new received data signal recdatavalid : std_logic; -- wordcounter , one more (no -1) to shift crc signal wordcounter : integer range 0 to numwords-1; -- CRC reset signal signal reset_crc : std_logic; -- CRC enable signal signal crc_en : std_logic; -- CRC Match signal signal crc_match : std_logic; -- CRC value signal signal crcout : std_logic_vector(31 downto 0); -- recdata or 0000 signal crc_data : std_logic_vector(31 downto 0); -- SCSN register addr 0 signal receiver_en : std_logic; -- SCSN register addr 1 signal packetcounter : std_logic_vector(31 downto 0); -- SCSN register addr 2 signal crcerrorcounter : std_logic_vector(31 downto 0); -- SCSN unused control signal signal req_i : std_logic; begin -- behv -- sync input din_syncer : process (clk40, reset_n) begin -- process din_syncer if reset_n = '0' then -- asynchronous reset (active low) din_syn <= (others => '1'); elsif clk40'event and clk40 = '1' then -- rising clock edge din_syn <= din; end if; end process din_syncer; -- delay by 1 clk40 din_delayer : process (clk40, reset_n) begin -- process din_syncer if reset_n = '0' then -- asynchronous reset (active low) din_del1 <= (others => '1'); elsif clk40'event and clk40 = '1' then -- rising clock edge din_del1 <= din_syn; end if; end process din_delayer; -- samplecounter synced to SOF cr_gt_one : if clkratio /= 1 generate samplcnt_p : process (clk40, reset_n) begin -- process samplcnt_p if reset_n = '0' then -- asynchronous reset (active low) receiving <= '0'; sample_cnt <= 0; elsif clk40'event and clk40 = '1' then -- rising clock edge if receiving = '0' then if din_del1(7) = '0' and receiver_en = '1' then receiving <= '1'; sample_cnt <= sample_cnt + 1; end if; else if packet_done = '1' or receiver_en='0' then receiving <= '0'; sample_cnt <= 0; elsif sample_cnt = (clkratio-1) then sample_cnt <= 0; else sample_cnt <= sample_cnt + 1; end if; end if; end if; end process samplcnt_p; samplepoint <= '1' when sample_cnt = (clkratio-1) else '0'; end generate cr_gt_one; -- samplecounter always one cr_eq_one : if clkratio = 1 generate samplcnt_p : process (clk40, reset_n) begin -- process samplcnt_p if reset_n = '0' then -- asynchronous reset (active low) receiving <= '0'; elsif clk40'event and clk40 = '1' then -- rising clock edge if receiving = '0' then if din_syn(7) = '0' and receiver_en = '1' then receiving <= '1'; end if; elsif packet_done = '1' or receiver_en='0' then receiving <= '0'; end if; end if; end process samplcnt_p; samplepoint <= receiving; end generate cr_eq_one; -- bitcounter synced to SOF bitcnt_p : process (clk40, reset_n) begin -- process bitcnt_p if reset_n = '0' then -- asynchronous reset (active low) bitcnt <= 0; datavalid <= '0'; elsif clk40'event and clk40 = '1' then -- rising clock edge if receiving = '0' then bitcnt <= 0; datavalid <= '0'; elsif samplepoint = '1' then if bitcnt = 3 then bitcnt <= 0; datavalid <= '1'; else bitcnt <= bitcnt + 1; datavalid <= '0'; end if; else datavalid <= '0'; end if; end if; end process bitcnt_p; -- Store received data to memory when datavalid goes high mem_p : process (clk40, reset_n) begin -- process mem_p if reset_n = '0' then -- asynchronous reset (active low) recdatamem <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge if datavalid = '1' then recdatamem <= recdata; end if; end if; end process mem_p; -- recdatavalid is one cycle after datavalid, to putput do_valid rcvalid_p : process (clk40, reset_n) begin -- process rcvalid_p if reset_n = '0' then -- asynchronous reset (active low) recdatavalid <= '0'; elsif clk40'event and clk40 = '1' then -- rising clock edge recdatavalid <= datavalid; end if; end process rcvalid_p; do <= recdatamem; do_strobe <= recdatavalid; -- Count received words wordcnt_p : process (clk40, reset_n) begin -- process wordcnt_p if reset_n = '0' then -- asynchronous reset (active low) wordcounter <= 0; packet_done <= '0'; elsif clk40'event and clk40 = '1' then -- rising clock edge if receiving = '0' then wordcounter <= 0; packet_done <= '0'; elsif datavalid = '1' then if wordcounter = numwords-1 then wordcounter <= 0; packet_done <= '1'; else wordcounter <= wordcounter + 1; packet_done <= '0'; end if; else packet_done <= '0'; end if; end if; end process wordcnt_p; crc_en <= '1' when datavalid = '1' and (wordcounter /= (numwords - 1)) else '0'; reset_crc <= not receiving; crc_data <= recdata; -- when wordcounter /= numwords else x"00000000"; crc_match <= '1' when (crcout = recdatamem) and (packet_done = '1') else '0'; ucrc_par_1 : ucrc_par generic map ( POLYNOMIAL => x"04C11DB7", INIT_VALUE => x"00000000", DATA_WIDTH => 32, SYNC_RESET => 1) port map ( clk_i => clk40, rst_i => reset_crc, clken_i => crc_en, data_i => crc_data, match_o => open, crc_o => crcout); -- 8 input desiraliser sfrs : for i in 7 downto 0 generate cbbr_iserdes_1 : cbbr_iserdes port map ( clk40 => clk40, reset_n => reset_n, di => din_del1(i), enable => samplepoint, dout => recdata(i*4+3 downto i*4)); end generate sfrs; -- SCSN register 0 rec_en : process (clk40, reset_n) begin -- process rec_en if reset_n = '0' then -- asynchronous reset (active low) receiver_en <= '0'; elsif clk40'event and clk40 = '1' then -- rising clock edge if address = "0000" and we = '1' then receiver_en <= cbbr_IBO(0); end if; end if; end process rec_en; -- SCSN register 1 packetcounter packetcounterp : process (clk40, reset_n) begin -- process packetcounter if reset_n = '0' then -- asynchronous reset (active low) packetcounter <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge if address = "0001" and we = '1' then packetcounter <= (others => '0'); elsif packet_done = '1' then packetcounter <= packetcounter + '1'; end if; end if; end process packetcounterp; -- SCSN register 1 crc error counter crcerrorcounterp : process (clk40, reset_n) begin -- process packetcounter if reset_n = '0' then -- asynchronous reset (active low) crcerrorcounter <= (others => '0'); elsif clk40'event and clk40 = '1' then -- rising clock edge if address = "0010" and we = '1' then crcerrorcounter <= (others => '0'); elsif packet_done = '1' and crc_match = '0' then crcerrorcounter <= crcerrorcounter + '1'; end if; end if; end process crcerrorcounterp; -- read demux with address select cbbr_OBI <= ((31 downto 1 => '0') & receiver_en) when "0000", packetcounter when "0001", crcerrorcounter when "0010", x"42424242" when "0011", (31 downto 0 => '0') when others; -- SCSN control sig ack <= '1'; req_i <= req; end behv;