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