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

📄 receiver.vhd

📁 无线耳机通讯用CPLD的VHDL源码
💻 VHD
字号:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use work.Wireless_USB_pack.all;
use IEEE.std_logic_ARITH.all;   				   
entity RECEIVER is
	port (	  	
		CLK: in STD_LOGIC;									   -- 24MHz clock input
		RESET: in STD_LOGIC;								   -- Master reset pin (1 = resets logic)
		RD : in STD_LOGIC;									   -- Controller READS parallel DATA byte (active high)	
		SERIAL_DATA_IN: in STD_LOGIC;						   -- Asynchronous serial input from RF-Modem
		PARALLEL_DATA_OUT: out STD_LOGIC_VECTOR (7 downto 0);  -- Parallel DATA byte outputs to controller
		RECEIVER_FULL: out STD_LOGIC;						   -- When '1' logic is ready to transfer byte to the Controller
		RECEIVER_LOCKED: out STD_LOGIC;						   -- When goes low, logic detected valid preamble and start bit when goes high, logic is no longer locked on a packet
		PREAMBLE: in STD_LOGIC_VECTOR (7 downto 0)			   -- preamble low byte correlation code
	);
end RECEIVER;

--THE BEHAVE OF RECEIVER IS DIVIDED TO 3 MODES 
--BEFORE LOCKING ON PREAMBLE- WHERE WE ARE SEARCHING FOR CORRELATION . 
--AFTER WE ARE LOCKED AND WE ARE HANDELING THE INCOMING DATA .
--AND A MODE WHEN SOMETHING WRONG WITH THE PACKETE  AND WE GO BACK TO FIND NEW CORRELATON

architecture behave of RECEIVER is

-- THE PREAMBLE FIND MODE IS DIVIDED TO 4 STATES 
type state_type_1 is (FIRST_START_BIT_RISING_DETECT,   
					START_BIT_FALLING_DETECT,		  
					SILENCE_CHECK,					    
					PREAMBLE_DATA_SAMPLE);

-- THE LOCKED_ON_PACKET MODE IS DIVIDED TO 4 STATES
type state_type_2 is (FALLING_DETECT,
					START_BIT_SAMPLE,
					SILENCE_CHECKING,
					DATA_SAMPLE);

type mode_status is ( PREAMBLE_FIND, LOCKED_ON_PACKET,OUT_OF_LOCKING );

signal mode : mode_status;
signal state_2 : state_type_2;
signal state_1 : state_type_1;
signal byte_data		 : std_logic_vector (7 downto 0);
signal data_reg_vect     : std_logic_vector (PREAMBLE_CORRELATION_LENGTH-1 downto 0);
signal shift_count 	  	 : integer range 7 downto 0; 
signal pulse_width_count : integer range 15 downto 0;
signal window_cnt 	     : integer range (PULSE_CLOCK_COUNT + 8) downto 0;
signal data_bit_sample	 : integer range 15 downto 0;
signal data_byte_flag	 : std_logic;
signal byte_sample		 : std_logic;
signal vect_bit			 : std_logic;
signal interval_generator: integer range (BIT_INTERVAL-1) downto 0;

begin
	
	-- swap LSB to MSB order 
	endian_conversion: for i in 0 to 7 generate 
		parallel_data_out(i) <= byte_data(7-i);
	end generate; 

	process (CLK, RESET)
	begin
 		if (RESET = '1') then		   
			data_reg_vect <= (others => '0');
			mode <= PREAMBLE_FIND;
			state_1 <= FIRST_START_BIT_RISING_DETECT;
			state_2 <= FALLING_DETECT;
			shift_count <= 0;
			receiver_full <= '0';
			receiver_locked <= '1';
			window_cnt <= 0;
 			data_bit_sample <= 0;
			pulse_width_count <= 0;
			byte_data <= (others => '0');
			data_byte_flag <= '0';
			byte_sample	<= '0';	
			vect_bit <= '0';   
			interval_generator <= 0;

		elsif rising_edge(CLK) then
			
			-- generate 24 clocks timer thet equal to  1usec (bit period)			 
			if (interval_generator = (BIT_INTERVAL-1)) then
				interval_generator <= 0;
			else
				interval_generator <= (interval_generator + 1);
			end if;


		  	-- Generate pulse width check counter, counts how many clocks the input is '1'
			if (serial_data_in = '1') then
				pulse_width_count <= (pulse_width_count + 1) mod MAX_PULSE_INTERVAL_COUNT;
			else
				pulse_width_count <= 0;
			end if;


			-- Reset full flag upon read command
			if (rd = '1') then
				receiver_full <= '0';
			end if;
			
			
			-- sets receiver flag and loads the byte of data out buffer
			if data_byte_flag = '1' then
				byte_data <= data_reg_vect(7 downto 0);
				receiver_full <= '1';
				data_byte_flag <= '0';
			end if;	  
			
	 case mode is

		 		when PREAMBLE_FIND =>

		  			case STATE_1 is	 
						  
						-- detects the first pulse of the preamble
				 		-- look for a rising edge of a start bit, and then store it as data_bit
						-- the bit considered '1' only after 7 successive '1' samples
						-- when ever we loses locking we come to this state from OUT_OF_LOCKING mode
						when FIRST_START_BIT_RISING_DETECT =>
					
						if serial_data_in = '1' then
							data_bit_sample <= data_bit_sample+1;	
							if data_bit_sample = MIN_PULSE_COUNT then 
								state_1 <= START_BIT_FALLING_DETECT;
								vect_bit <='1';
								interval_generator <= 0;
							end if;
						else 
							data_bit_sample <= 0;
						end if;	
						
						
						
						-- detect the falling edge of the pulse and then updates the vector(0), the value comes from vect_bit
						-- the vector is updated only in the falling edge to prevent from ilegal pulse 
						-- to be considered as '1' .
						-- when we detect a falling edge we tranfer to silence check
						when START_BIT_FALLING_DETECT =>
							if serial_data_in = '0' then
								-- Shift in the vect_bit  
							   	data_reg_vect(0) <= vect_bit;
								state_1 <= SILENCE_CHECK;
							end if;	

						-- checking for '0' between bits until 2 CLK before the next bit
						-- this check will stop and reset the preamble finding vector if it detects noise ( '1' instead of '0')
						-- if there no noise we will check for correlation and decide if we are locked or if we still need
						-- to sample more preamble bits
						-- we chek for silence between all the bits, and not only betweem S.B.
						when SILENCE_CHECK => 
							vect_bit <= '0';	  
			
							if serial_data_in ='1' then
								data_reg_vect <= (others => '0'); 
								data_bit_sample <=1;
								window_cnt <= 0; 
								state_1 <= FIRST_START_BIT_RISING_DETECT;
							elsif 	interval_generator = PULSE_CLOCK_COUNT then 
								data_bit_sample <= 0;
								if (data_reg_vect = ("1"& PREAMBLE )) then 
									receiver_locked <= '0';
									mode <= LOCKED_ON_PACKET;
									state_2 <= START_BIT_SAMPLE;
								else
									state_1 <= PREAMBLE_DATA_SAMPLE;
									receiver_locked <= '1';
								end if;
							end if;


			 			-- sampeling data in, in the window of => 2 clocks before pulse width and 2 clock after	
						-- a bit is considered  '1' only after 6 samples of '1'
						when PREAMBLE_DATA_SAMPLE =>
						   	if serial_data_in = '1' then
 					  			data_bit_sample <= data_bit_sample +1;
								 if data_bit_sample = MIN_PULSE_COUNT then
									vect_bit <= '1';
									interval_generator <= 0;  
								end if;
							end if;	
								
								
					  		if window_cnt = (PULSE_CLOCK_COUNT+4) then
					  			window_cnt <= 0;
								state_1 <= START_BIT_FALLING_DETECT; 
								data_reg_vect(PREAMBLE_CORRELATION_LENGTH-1 downto 1) <= data_reg_vect(PREAMBLE_CORRELATION_LENGTH-2 downto 0);
					  		else window_cnt <= window_cnt + 1;
					  		end if;
				   end case;
					   
			-- check for invalid pulse width
			-- the check is made for all pulses and when the pulse is to long we go to OUT_OF_LOCKING mode		
			if (pulse_width_count = MAX_PULSE_INTERVAL_COUNT) then
				mode <= OUT_OF_LOCKING;
			end if;
			
				when LOCKED_ON_PACKET =>
					
				-- check for invalid pulse width
				-- the check is made for all pulses and when the pulse is to long we go to OUT_OF_LOCKING mode	
					if (pulse_width_count = MAX_PULSE_INTERVAL_COUNT) then
					   mode <= OUT_OF_LOCKING;
					end if;
					receiver_locked <= '0';	
					
					case STATE_2 is
						
						 -- wait for the falling edge of the  bit then go check for silence
						when FALLING_DETECT =>
							if serial_data_in = '0' then
								state_2 <= SILENCE_CHECKING;
							end if;	


					   	-- checking for 0 between bits until 2 CLK before the next one
						-- this check will stop and reset the preamble vector  if noise will apear between bits
						-- if there no noise we will sample the data as data
						when SILENCE_CHECKING => 
							vect_bit <= '0';
							if serial_data_in = '1' then
							   mode <= OUT_OF_LOCKING;
							elsif interval_generator = PULSE_CLOCK_COUNT then 
								if byte_sample = '1' then
									state_2 <= DATA_SAMPLE;
									data_reg_vect(PREAMBLE_CORRELATION_LENGTH-1 downto 1) <= data_reg_vect(PREAMBLE_CORRELATION_LENGTH-2 downto 0);
								else
 								 	state_2 <= START_BIT_SAMPLE;
									window_cnt <= 0;
								end if;
							end if;


						when START_BIT_SAMPLE =>
						-- we sample for S.B. in a window of +,-  2 clock 
						-- if we didn't find S.B. we go to - out of locking mode.
					
							window_cnt <= window_cnt + 1;
						  	if serial_data_in = '1' then
 					  			data_bit_sample <= data_bit_sample +1;
								if data_bit_sample = MIN_PULSE_COUNT then
									vect_bit <= '1';
							   		interval_generator <= 0;
									state_2 <= FALLING_DETECT;
									shift_count <= 0;
									byte_sample <= '1';
								end if;
							end if;	
											
						 	if (window_cnt = (PULSE_CLOCK_COUNT+3)) then
								mode <= OUT_OF_LOCKING;
							end if;

						
						when DATA_SAMPLE =>	
							data_bit_sample <= 0;
						-- here we sample the 8 data information coming from serial_in ,
						-- we sample each bit, every 1 bit time. we sample the value in middle of 
						-- the pulse. when we finish 1 byte we go look for the next S.B. after we detect falling edge
							if interval_generator = (BIT_INTERVAL-1) then 
								data_reg_vect(0) <= serial_data_in;
								state_2 <= FALLING_DETECT;
						 		-- Increment data bit count
	 							if  shift_count = 7 then
						    		shift_count <= 0;
						    		data_byte_flag <= '1';
									byte_sample <= '0';
								else 
						    		shift_count <= shift_count + 1;
								end if;	
							 end if;		
					end case; 
			
				when OUT_OF_LOCKING => 
				-- when ever we detect problems in the packet we come to this state and initilaize 
				-- all relevant signals before  new preamble  searching. 
					data_reg_vect <= (others => '0');
					mode <= PREAMBLE_FIND;
					state_1 <= FIRST_START_BIT_RISING_DETECT;
					receiver_locked <= '1';
					window_cnt <= 0;
 					data_bit_sample <= 0;		
					vect_bit <= '0'; 
			end case;			
		end if;
		
	end process;
end behave;

⌨️ 快捷键说明

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