diff --git a/README.md b/README.md index 1833cc4..e35ce3f 100644 --- a/README.md +++ b/README.md @@ -7,17 +7,32 @@ This repository contains the VHDL files for the course "Digital Synthese: practi - Transmitter (top file) - access layer: PNGenerator, MUX - datalink layer: SequenceController, DataRegister - - application layer: EdgeDetector, UpDownCounter, Debouncer, SegDecoder + - application layer: EdgeDetector, UpDownCounter, Debouncer, SegDecoder - Receiver (top file) - access layer: SegDecoder, DataLatch - datalink layer: DataShiftReg - application layer: DPLL, MatchedFilter, Correlator, Despreader, MUX, PNGenerator, Edgedetector -- Hardware UCF (Xilinx FPGA file) - - transmitter - - receiver +- Hardware + - transmitter: Xilinx UCF file, Transmitter hardware top file + - receiver: Xilinx UCF file, Receiver hardware top file + +## Testbench (total_test.vhd) +![Total testbench](docs/total_testbench.png "Total testbench") + +## Result +A fully working DSSS Wireless Transmit-Receive System with 3 different PN codes. + +

+2 Virtex II Pro FPGA as a DSSS Wireless Transmit-Receive System +

+

+Wireless extension board for the Virtex II Pro FPGA +

+

+Demo +

## License Everything in this repository is available under the GPLv3 License. - diff --git a/docs/demo.gif b/docs/demo.gif new file mode 100644 index 0000000..4873367 Binary files /dev/null and b/docs/demo.gif differ diff --git a/docs/deployment1.jpg b/docs/deployment1.jpg new file mode 100644 index 0000000..dbcc2b2 Binary files /dev/null and b/docs/deployment1.jpg differ diff --git a/docs/deployment2.jpg b/docs/deployment2.jpg new file mode 100644 index 0000000..c02c64b Binary files /dev/null and b/docs/deployment2.jpg differ diff --git a/docs/total_testbench.png b/docs/total_testbench.png new file mode 100644 index 0000000..a7dd91d Binary files /dev/null and b/docs/total_testbench.png differ diff --git a/hardware/README.md b/hardware/README.md new file mode 100644 index 0000000..c58a919 --- /dev/null +++ b/hardware/README.md @@ -0,0 +1,11 @@ +# Deployment +## What do you need? +- FPGA platform (Virtex II Pro) +- VHDL compiler +- FPGA upload software, see the website of the FPGA manufacturer + +## Steps +- Compile the VHDL code using a VHDL compiler. The top and UCF files for the Virtex II Pro platform are included in this repo. +- Upload the bitfile to the FPGA using the upload software from your manufacturer. +- Press the reset button to initialize the FPGA. +- Enjoy! diff --git a/hardware/receiver/nco.vhd b/hardware/receiver/nco.vhd new file mode 100644 index 0000000..b6e148b --- /dev/null +++ b/hardware/receiver/nco.vhd @@ -0,0 +1,66 @@ +--*************************************** +--* TITLE: NCO (receiver) * +--* TYPE: Component * +--* AUTHOR: Dylan Van Assche * +--* DATE: 13/12/2017 * +--*************************************** +--*************** +--* DESCRIPTION * +--*************** +--1)Purpose: +-- NCO to divide the 100 Mhz clock of the Virtex II Pro. +--2)Principle: +-- When counting down, send a clk_en signal out and restart. +--3)Ingangen: +-- rst, clk +--4)Uitgangen: +-- clk_en +--********************** +--* LIBRARIES & ENTITY * +--********************** +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.std_logic_unsigned.ALL; +ENTITY nco_rx IS + PORT + ( + clk : IN std_logic; + rst : IN std_logic; + clk_en : OUT std_logic + ); +END; +--********************************************* +--* ARCHITECTURE, SIGNALS, TYPES & COMPONENTS * +--********************************************* +ARCHITECTURE behavior OF nco_rx IS + SIGNAL n_count : std_logic_vector(10 DOWNTO 0); + SIGNAL p_count : std_logic_vector(10 DOWNTO 0); + SIGNAL enable : std_logic := '1'; -- allow for reset + SIGNAL enable_next : std_logic := '0'; + CONSTANT TRIGGER : std_logic_vector(10 DOWNTO 0) := (OTHERS => '0'); +BEGIN +clk_en <= enable; +-- 2-Process: synchronous part +count_sync : PROCESS (clk) +BEGIN + IF (rising_edge(clk)) THEN + IF (rst = '1') THEN -- rst line high, go to initial state + p_count <= (OTHERS => '0'); + enable <= '1'; + ELSE -- normal operation + p_count <= n_count; + enable <= enable_next; + END IF; + END IF; +END PROCESS count_sync; +-- 2-Process: combinatoric part +count_comb : PROCESS (p_count, enable) +BEGIN + n_count <= p_count + 1; + IF (n_count = TRIGGER) THEN -- clk_en signal + enable_next <= '1'; + ELSE + enable_next <= '0'; + END IF; +END PROCESS count_comb; +END behavior; \ No newline at end of file diff --git a/hardware/receiver.ucf b/hardware/receiver/receiver.ucf similarity index 90% rename from hardware/receiver.ucf rename to hardware/receiver/receiver.ucf index 6d21361..cd34fe3 100644 --- a/hardware/receiver.ucf +++ b/hardware/receiver/receiver.ucf @@ -8,9 +8,9 @@ #**************** #* CLOCK 100MHz * #**************** -Net clk_100mhz LOC="AJ15"; -Net clk_100mhz IOSTANDARD = LVCMOS25; -Net clk_100mhz PERIOD = 10000 ps; +NET clk LOC="AJ15"; +NET clk IOSTANDARD = LVCMOS25; +NET clk PERIOD = 10000 ps; #********************* #* 7 SEGMENT DISPLAY * diff --git a/hardware/receiver.vhd b/hardware/receiver/receiver.vhd similarity index 90% rename from hardware/receiver.vhd rename to hardware/receiver/receiver.vhd index 09a6493..a83109e 100644 --- a/hardware/receiver.vhd +++ b/hardware/receiver/receiver.vhd @@ -1,105 +1,105 @@ ---*************************************** ---* TITLE: Receiver (receiver) * ---* TYPE: Top File * ---* AUTHOR: Dylan Van Assche * ---* DATE: 9/12/2017 * ---*************************************** ---*************** ---* DESCRIPTION * ---*************** ---1)Purpose: --- Connect all the layers into 1 VHDL file. ---2)Principle: --- Connect every layer API. ---3)Inputs: --- rx, pn_select, rst, clk, clk_en ---4)Outputs: --- display_b ---********************** ---* LIBRARIES & ENTITY * ---********************** -LIBRARY IEEE; -USE IEEE.std_logic_1164.ALL; -ENTITY receiver IS - PORT - ( - clk : IN std_logic; - rst_b : IN std_logic; - rx : IN std_logic; - pn_select_b_SW0 : IN std_logic; - pn_select_b_SW1 : IN std_logic; - display_b_SEG_A : OUT std_logic; - display_b_SEG_B : OUT std_logic; - display_b_SEG_C : OUT std_logic; - display_b_SEG_D : OUT std_logic; - display_b_SEG_E : OUT std_logic; - display_b_SEG_F : OUT std_logic; - display_b_SEG_G : OUT std_logic; - display_b_SEG_DP: OUT std_logic - ); -END receiver ; -ARCHITECTURE behavior OF receiver IS - SIGNAL bitsample : std_logic; - SIGNAL databit : std_logic; - SIGNAL rst_b : std_logic; - SIGNAL clk_en : std_logic; - SIGNAL preamble : std_logic_vector(6 DOWNTO 0); - SIGNAL data : std_logic_vector(3 DOWNTO 0); -- received number from transmitter - SIGNAL display_b : std_logic_vector(6 DOWNTO 0); - SIGNAL pn_select: std_logic_vector(1 DOWNTO 0); -BEGIN --- display outputs -display_b_SEG_A <= display_b(6); -display_b_SEG_B <= display_b(5); -display_b_SEG_C <= display_b(4); -display_b_SEG_D <= display_b(3); -display_b_SEG_E <= display_b(2); -display_b_SEG_F <= display_b(1); -display_b_SEG_G <= display_b(0); -display_b_SEG_DP <= '1'; -- turn DOT off --- dipswitch inputs -pn_select <= NOT(pn_select_b_SW1) & NOT(pn_select_b_SW0) --- buttons inputs -rst <= NOT(rst_b); ---layers -nco_rx : ENTITY work.nco_rx(behavior) -PORT MAP -( - clk => clk, - rst => rst, - clk_en => clk_en -); -application_layer : ENTITY work.application_layer(behavior) -PORT MAP -( - clk => clk, - clk_en => clk_en, - rst => rst, - bitsample => bitsample, - preamble => preamble, - data_in => data, - display_b => display_b -); -datalink_layer : ENTITY work.datashiftreg(behavior) -- datalink layer is only 1 component -PORT MAP -( - clk => clk, - clk_en => clk_en, - rst => rst, - bitsample => bitsample, - databit => databit, - preamble => preamble, - data => data -); -access_layer : ENTITY work.access_layer(behavior) -PORT MAP -( - clk => clk, - clk_en => clk_en, - rst => rst, - sdi_spread => rx, - pn_select => pn_select, - bitsample_out => bitsample, - databit => databit -); +--*************************************** +--* TITLE: Receiver (receiver) * +--* TYPE: Top File * +--* AUTHOR: Dylan Van Assche * +--* DATE: 9/12/2017 * +--*************************************** +--*************** +--* DESCRIPTION * +--*************** +--1)Purpose: +-- Connect all the layers into 1 VHDL file. +--2)Principle: +-- Connect every layer API. +--3)Inputs: +-- rx, pn_select, rst, clk, clk_en +--4)Outputs: +-- display_b +--********************** +--* LIBRARIES & ENTITY * +--********************** +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +ENTITY receiver_hw IS + PORT + ( + clk : IN std_logic; + rst_b : IN std_logic; + rx : IN std_logic; + pn_select_b_SW0 : IN std_logic; + pn_select_b_SW1 : IN std_logic; + display_b_SEG_A : OUT std_logic; + display_b_SEG_B : OUT std_logic; + display_b_SEG_C : OUT std_logic; + display_b_SEG_D : OUT std_logic; + display_b_SEG_E : OUT std_logic; + display_b_SEG_F : OUT std_logic; + display_b_SEG_G : OUT std_logic; + display_b_SEG_DP: OUT std_logic + ); +END receiver_hw; +ARCHITECTURE behavior OF receiver_hw IS + SIGNAL bitsample : std_logic; + SIGNAL databit : std_logic; + SIGNAL rst : std_logic; + SIGNAL clk_en : std_logic; + SIGNAL preamble : std_logic_vector(6 DOWNTO 0); + SIGNAL data : std_logic_vector(3 DOWNTO 0); -- received number from transmitter + SIGNAL display_b : std_logic_vector(6 DOWNTO 0); + SIGNAL pn_select: std_logic_vector(1 DOWNTO 0); +BEGIN +-- display outputs +display_b_SEG_A <= display_b(6); +display_b_SEG_B <= display_b(5); +display_b_SEG_C <= display_b(4); +display_b_SEG_D <= display_b(3); +display_b_SEG_E <= display_b(2); +display_b_SEG_F <= display_b(1); +display_b_SEG_G <= display_b(0); +display_b_SEG_DP <= '1'; -- turn DOT off +-- dipswitch inputs +pn_select <= NOT(pn_select_b_SW1) & NOT(pn_select_b_SW0); +-- buttons inputs +rst <= NOT(rst_b); +--layers +nco_rx : ENTITY work.nco_rx(behavior) +PORT MAP +( + clk => clk, + rst => rst, + clk_en => clk_en +); +application_layer : ENTITY work.application_layer(behavior) +PORT MAP +( + clk => clk, + clk_en => clk_en, + rst => rst, + bitsample => bitsample, + preamble => preamble, + data_in => data, + display_b => display_b +); +datalink_layer : ENTITY work.datashiftreg(behavior) -- datalink layer is only 1 component +PORT MAP +( + clk => clk, + clk_en => clk_en, + rst => rst, + bitsample => bitsample, + databit => databit, + preamble => preamble, + data => data +); +access_layer : ENTITY work.access_layer(behavior) +PORT MAP +( + clk => clk, + clk_en => clk_en, + rst => rst, + sdi_spread => rx, + pn_select => pn_select, + bitsample_out => bitsample, + databit => databit +); END behavior; \ No newline at end of file diff --git a/hardware/transmitter/nco.vhd b/hardware/transmitter/nco.vhd new file mode 100644 index 0000000..a30754c --- /dev/null +++ b/hardware/transmitter/nco.vhd @@ -0,0 +1,66 @@ +--*************************************** +--* TITLE: NCO (transmitter) * +--* TYPE: Component * +--* AUTHOR: Dylan Van Assche * +--* DATE: 13/12/2017 * +--*************************************** +--*************** +--* DESCRIPTION * +--*************** +--1)Purpose: +-- NCO to divide the 100 Mhz clock of the Virtex II Pro. +--2)Principle: +-- When counting down, send a clk_en signal out and restart. +--3)Ingangen: +-- rst, clk +--4)Uitgangen: +-- clk_en +--********************** +--* LIBRARIES & ENTITY * +--********************** +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.std_logic_unsigned.ALL; +ENTITY nco_tx IS + PORT + ( + clk : IN std_logic; + rst : IN std_logic; + clk_en : OUT std_logic + ); +END; +--********************************************* +--* ARCHITECTURE, SIGNALS, TYPES & COMPONENTS * +--********************************************* +ARCHITECTURE behavior OF nco_tx IS + SIGNAL n_count : std_logic_vector(14 DOWNTO 0); + SIGNAL p_count : std_logic_vector(14 DOWNTO 0); + SIGNAL enable : std_logic := '1'; -- allow for reset + SIGNAL enable_next : std_logic := '0'; + CONSTANT TRIGGER : std_logic_vector(14 DOWNTO 0) := (OTHERS => '0'); +BEGIN +clk_en <= enable; +-- 2-Process: synchronous part +count_sync : PROCESS (clk) +BEGIN + IF (rising_edge(clk)) THEN + IF (rst = '1') THEN -- rst line high, go to initial state + p_count <= (OTHERS => '0'); + enable <= '1'; + ELSE -- normal operation + p_count <= n_count; + enable <= enable_next; + END IF; + END IF; +END PROCESS count_sync; +-- 2-Process: combinatoric part +count_comb : PROCESS (p_count, enable) +BEGIN + n_count <= p_count + 1; + IF (n_count = TRIGGER) THEN -- clk_en signal + enable_next <= '1'; + ELSE + enable_next <= '0'; + END IF; +END PROCESS count_comb; +END behavior; \ No newline at end of file diff --git a/hardware/transmitter.ucf b/hardware/transmitter/transmitter.ucf similarity index 91% rename from hardware/transmitter.ucf rename to hardware/transmitter/transmitter.ucf index 747aca1..5b2b798 100644 --- a/hardware/transmitter.ucf +++ b/hardware/transmitter/transmitter.ucf @@ -8,9 +8,9 @@ #**************** #* CLOCK 100MHz * #**************** -Net clk_100mhz LOC="AJ15"; -Net clk_100mhz IOSTANDARD = LVCMOS25; -Net clk_100mhz PERIOD = 10000 ps; +NET clk LOC="AJ15"; +NET clk IOSTANDARD = LVCMOS25; +NET clk PERIOD = 10000 ps; #********************* #* 7 SEGMENT DISPLAY * diff --git a/hardware/transmitter.vhd b/hardware/transmitter/transmitter.vhd similarity index 91% rename from hardware/transmitter.vhd rename to hardware/transmitter/transmitter.vhd index 5999f21..d01f380 100644 --- a/hardware/transmitter.vhd +++ b/hardware/transmitter/transmitter.vhd @@ -1,109 +1,109 @@ ---*************************************** ---* TITLE: Transmitter (transmitter) * ---* TYPE: Top File * ---* AUTHOR: Dylan Van Assche * ---* DATE: 25/10/2017 * ---*************************************** ---*************** ---* DESCRIPTION * ---*************** ---1)Purpose: --- Connect all the layers into 1 VHDL file. ---2)Principle: --- Connect every layer API. ---3)Inputs: --- up, down, pn_select, rst, clk, clk_en ---4)Outputs: --- tx ---********************** ---* LIBRARIES & ENTITY * ---********************** -LIBRARY IEEE; -USE IEEE.std_logic_1164.ALL; -ENTITY transmitter IS - PORT - ( - clk : IN std_logic; - rst_b : IN std_logic; - up_b : IN std_logic; - down_b : IN std_logic; - pn_select_b_SW0 : IN std_logic; - pn_select_b_SW1 : IN std_logic; - display_b_SEG_A : OUT std_logic; - display_b_SEG_B : OUT std_logic; - display_b_SEG_C : OUT std_logic; - display_b_SEG_D : OUT std_logic; - display_b_SEG_E : OUT std_logic; - display_b_SEG_F : OUT std_logic; - display_b_SEG_G : OUT std_logic; - display_b_SEG_DP: OUT std_logic; - tx : OUT std_logic - ); -END transmitter ; -ARCHITECTURE behavior OF transmitter IS - SIGNAL pn_start : std_logic; - SIGNAL payload : std_logic; - SIGNAL clk_en : std_logic := '1'; -- allow reset without NCO - SIGNAL rst : std_logic; - SIGNAL up : std_logic; - SIGNAL down : std_logic; - SIGNAL counter : std_logic_vector(3 DOWNTO 0); - SIGNAL display_b: std_logic_vector(6 DOWNTO 0); - SIGNAL pn_select: std_logic_vector(1 DOWNTO 0); -BEGIN --- display outputs -display_b_SEG_A <= display_b(6); -display_b_SEG_B <= display_b(5); -display_b_SEG_C <= display_b(4); -display_b_SEG_D <= display_b(3); -display_b_SEG_E <= display_b(2); -display_b_SEG_F <= display_b(1); -display_b_SEG_G <= display_b(0); -display_b_SEG_DP <= '1'; -- turn DOT off --- dipswitch inputs -pn_select <= NOT(pn_select_b_SW1) & NOT(pn_select_b_SW0) --- buttons inputs -rst <= NOT(rst_b); -up <= NOT(up_b); -down <= NOT(down_b); ---layers -nco_tx : ENTITY work.nco_tx(behavior) -PORT MAP -( - clk => clk, - rst => rst, - clk_en => clk_en -); -application_layer_tx : ENTITY work.application_layer_tx(behavior) -PORT MAP -( - clk => clk, - clk_en => clk_en, - rst => rst, - up => up, - down => down, - display_b => display_b, - output => counter -); -datalink_layer_tx : ENTITY work.datalink_layer_tx(behavior) -PORT MAP -( - clk => clk, - clk_en => clk_en, - rst => rst, - pn_start => pn_start, - output => payload, - data => counter -); -access_layer_tx : ENTITY work.access_layer_tx(behavior) -PORT MAP -( - clk => clk, - clk_en => clk_en, - rst => rst, - pn_select => pn_select, - pn_start => pn_start, - tx => tx, - data => payload -); +--*************************************** +--* TITLE: Transmitter (transmitter) * +--* TYPE: Top File * +--* AUTHOR: Dylan Van Assche * +--* DATE: 25/10/2017 * +--*************************************** +--*************** +--* DESCRIPTION * +--*************** +--1)Purpose: +-- Connect all the layers into 1 VHDL file. +--2)Principle: +-- Connect every layer API. +--3)Inputs: +-- up, down, pn_select, rst, clk, clk_en +--4)Outputs: +-- tx +--********************** +--* LIBRARIES & ENTITY * +--********************** +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +ENTITY transmitter_hw IS + PORT + ( + clk : IN std_logic; + rst_b : IN std_logic; + up_b : IN std_logic; + down_b : IN std_logic; + pn_select_b_SW0 : IN std_logic; + pn_select_b_SW1 : IN std_logic; + display_b_SEG_A : OUT std_logic; + display_b_SEG_B : OUT std_logic; + display_b_SEG_C : OUT std_logic; + display_b_SEG_D : OUT std_logic; + display_b_SEG_E : OUT std_logic; + display_b_SEG_F : OUT std_logic; + display_b_SEG_G : OUT std_logic; + display_b_SEG_DP: OUT std_logic; + tx : OUT std_logic + ); +END transmitter_hw ; +ARCHITECTURE behavior OF transmitter_hw IS + SIGNAL pn_start : std_logic; + SIGNAL payload : std_logic; + SIGNAL clk_en : std_logic := '1'; -- allow reset without NCO + SIGNAL rst : std_logic; + SIGNAL up : std_logic; + SIGNAL down : std_logic; + SIGNAL counter : std_logic_vector(3 DOWNTO 0); + SIGNAL display_b: std_logic_vector(6 DOWNTO 0); + SIGNAL pn_select: std_logic_vector(1 DOWNTO 0); +BEGIN +-- display outputs +display_b_SEG_A <= display_b(6); +display_b_SEG_B <= display_b(5); +display_b_SEG_C <= display_b(4); +display_b_SEG_D <= display_b(3); +display_b_SEG_E <= display_b(2); +display_b_SEG_F <= display_b(1); +display_b_SEG_G <= display_b(0); +display_b_SEG_DP <= '1'; -- turn DOT off +-- dipswitch inputs +pn_select <= NOT(pn_select_b_SW1) & NOT(pn_select_b_SW0); +-- buttons inputs +rst <= NOT(rst_b); +up <= NOT(up_b); +down <= NOT(down_b); +--layers +nco_tx : ENTITY work.nco_tx(behavior) +PORT MAP +( + clk => clk, + rst => rst, + clk_en => clk_en +); +application_layer_tx : ENTITY work.application_layer_tx(behavior) +PORT MAP +( + clk => clk, + clk_en => clk_en, + rst => rst, + up => up, + down => down, + display_b => display_b, + output => counter +); +datalink_layer_tx : ENTITY work.datalink_layer_tx(behavior) +PORT MAP +( + clk => clk, + clk_en => clk_en, + rst => rst, + pn_start => pn_start, + output => payload, + data => counter +); +access_layer_tx : ENTITY work.access_layer_tx(behavior) +PORT MAP +( + clk => clk, + clk_en => clk_en, + rst => rst, + pn_select => pn_select, + pn_start => pn_start, + tx => tx, + data => payload +); END behavior; \ No newline at end of file diff --git a/transmitter/datalink/datareg/datareg.vhd b/transmitter/datalink/datareg/datareg.vhd index 769cfde..934a409 100644 --- a/transmitter/datalink/datareg/datareg.vhd +++ b/transmitter/datalink/datareg/datareg.vhd @@ -41,7 +41,6 @@ END datareg; ARCHITECTURE behavior OF datareg IS SIGNAL reg: std_logic_vector(10 DOWNTO 0); SIGNAL reg_next: std_logic_vector(10 DOWNTO 0); - SIGNAL inverted_data: std_logic_vector(3 DOWNTO 0); CONSTANT PREAMBLE: std_logic_vector(6 DOWNTO 0) := "0111110"; BEGIN -- connect signal to output @@ -63,12 +62,11 @@ BEGIN -- load data, first PREAMBLE to reg(0) then the number of the counter -- Data is inverted otherwise the data is inverted when read out by the receiver, PREAMBLE is symmetric so it's not affected by this issue IF ld = '1' AND sh = '0' THEN - inverted_data <= data(0) & data(1) & data(2) & data(3); -- VHDL doesn't allow to invert the STD_LOGIC_VECTOR directly - reg_next <= inverted_data & PREAMBLE; + reg_next <= data(0) & data(1) & data(2) & data(3) & PREAMBLE; -- VHDL doesn't allow to invert the STD_LOGIC_VECTOR directly ELSIF ld = '0' AND sh = '1' THEN -- shift data, first preamble to reg(0) then the number of the counter reg_next <= '0' & reg(10 DOWNTO 1); -- Zeros added since load signal will occur as soon as zeros are arrived at the output ELSE -- Input signals wrong! reg_next <= reg; END IF; END PROCESS reg_comb; -END behavior; \ No newline at end of file +END behavior;