From 81a7fd8bd7af96a221c68b4b4fab44699b39ed10 Mon Sep 17 00:00:00 2001 From: Geoffrey Frogeye Date: Sat, 24 Feb 2018 18:16:09 +0100 Subject: [PATCH] FPGA : Communication sur plusieurs octets --- fpga/Principal.vhd | 91 ++++++++++-------------- fpga/Principal_tb.gtkw | 62 +++++++++++++++++ fpga/Principal_tb.vhd | 111 +++++++++++++++++++++++++++++ fpga/communication.vhd | 95 +++++++++++++++++++++++++ fpga/communication_tb.gtkw | 41 +++++++++++ fpga/communication_tb.vhd | 139 +++++++++++++++++++++++++++++++++++++ fpga/hcSr04.vhd | 1 - fpga/hcSr04Fulldiv.vhd | 69 ------------------ fpga/hedm.vhd | 6 +- fpga/project.cfg | 2 +- 10 files changed, 489 insertions(+), 128 deletions(-) create mode 100644 fpga/Principal_tb.gtkw create mode 100644 fpga/Principal_tb.vhd create mode 100644 fpga/communication.vhd create mode 100644 fpga/communication_tb.gtkw create mode 100644 fpga/communication_tb.vhd delete mode 100644 fpga/hcSr04Fulldiv.vhd diff --git a/fpga/Principal.vhd b/fpga/Principal.vhd index 281fb32..c10d9d2 100644 --- a/fpga/Principal.vhd +++ b/fpga/Principal.vhd @@ -1,5 +1,6 @@ library IEEE; use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; entity Principal is @@ -17,8 +18,8 @@ end Principal; architecture Behavioral of Principal is -- Blink led - signal pulse : std_logic := '0'; signal count : integer := 0; + signal theled: std_logic_vector(3 downto 0) := "0000"; -- General signal reset : std_logic := '0'; @@ -30,8 +31,6 @@ architecture Behavioral of Principal is -- Sensors signal front : integer; signal back : integer; - signal frontTrigger : integer := 0; - signal backTrigger : integer := 0; -- AF component uart is @@ -61,16 +60,22 @@ architecture Behavioral of Principal is signal rxData : std_logic_vector(7 downto 0); signal rxStb : std_logic := '0'; - constant A2FD_PING : std_logic_vector := x"50"; -- 'P' - - type readStates is (readIdle); - signal readState : readStates := readIdle; - - type sendMessages is (none, A2FD_PINGs); - signal resetSendMessageRead : std_logic := '0'; - signal resetSendMessageSend : std_logic := '0'; - signal sendMessage : sendMessages := none; - signal sendOffset : integer := 0; + -- Handling + component communication is + Port ( + clock : in std_logic; + reset : in std_logic; + left : in integer; + right : in integer; + front : in integer; + back : in integer; + txData : out std_logic_vector(7 downto 0); + txStb : out std_logic; + txAck : in std_logic; + rxData : in std_logic_vector(7 downto 0); + rxStb : in std_logic + ); + end component; -- Debug component sevenseg is @@ -100,63 +105,41 @@ begin rx => IO(20) ); - readsendFA : process(reset, rxStb, txAck) - begin - if reset = '1' then - readState <= readIdle; - sendMessage <= none; - txStb <= '0'; - sendOffset <= 0; - else - -- If read something - if rxStb = '1' then - if readState = readIdle then - case rxData is - when A2FD_PING => -- 'P' - sendMessage <= A2FD_PINGs; -- TODO Not so brutal - when others => - end case; - end if; - end if; + com: communication port map( + clock => CLK, + reset => reset, + left => left, + right => right, + front => front, + back => back, + txData => txData, + txStb => txStb, + txAck => txAck, + rxData => rxData, + rxStb => rxStb + ); - -- Reset sending if UART module has begun sending (and has a copy of the byte) - if txAck = '1' then - txStb <= '0'; - end if; - - -- If what was sent is acknowledged and there is still something to send - if txStb = '0' then - case sendMessage is - when none => - when A2FD_PINGs => - txData <= A2FD_PING; - txStb <= '1'; - sendMessage <= none; - end case; - end if; - end if; - end process; -- Debug blinkled : process(CLK, reset) begin if reset = '1' then count <= 0; - pulse <= '0'; + theled <= "0000"; elsif CLK'event and CLK = '1' then if count = 9999999 then count <= 0; - pulse <= not pulse; + theled(3) <= not theled(3); + theled(2 downto 0) <= "000"; else count <= count + 1; + theled(2 downto 0) <= theled(2 downto 0) or (txStb & rxStb & txAck); end if; + end if; end process; - LED(3) <= pulse; - LED(2) <= txStb; - LED(1) <= rxStb; - LED(0) <= txAck; + LED <= theled; debugSeg: sevenseg port map( data => sevensegdata, diff --git a/fpga/Principal_tb.gtkw b/fpga/Principal_tb.gtkw new file mode 100644 index 0000000..1e27c3d --- /dev/null +++ b/fpga/Principal_tb.gtkw @@ -0,0 +1,62 @@ +[*] +[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI +[*] Sun Feb 25 14:12:54 2018 +[*] +[dumpfile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/build/Principal_tb.vcd" +[dumpfile_mtime] "Sun Feb 25 14:10:51 2018" +[dumpfile_size] 38271255 +[savefile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/Principal_tb.gtkw" +[timestart] 0 +[size] 1680 1012 +[pos] -1 -1 +*-40.000000 3481820000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] dut. +[sst_width] 213 +[signals_width] 198 +[sst_expanded] 1 +[sst_vpaned_height] 296 +@28 +[color] 4 +clk +dut.reset +[color] 2 +dut.fa.rx_baud_tick +[color] 2 +dut.fa.rx +@8028 +[color] 2 +dut.fa.uart_rx_count[2:0] +@22 +[color] 2 +dut.fa.uart_rx_data_vec[7:0] +dut.rxdata[7:0] +@820 +dut.rxdata[7:0] +@28 +dut.rxstb +@420 +[color] 5 +dut.com.readoffset +[color] 5 +dut.com.sendoffset +@22 +[color] 4 +dut.txdata[7:0] +@820 +[color] 4 +dut.txdata[7:0] +@28 +dut.txstb +dut.txack +[color] 2 +dut.fa.tx +[color] 2 +dut.fa.tx_baud_tick +@8028 +[color] 2 +dut.fa.uart_tx_count[2:0] +@22 +[color] 2 +dut.fa.uart_tx_data_vec[7:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/fpga/Principal_tb.vhd b/fpga/Principal_tb.vhd new file mode 100644 index 0000000..6304b19 --- /dev/null +++ b/fpga/Principal_tb.vhd @@ -0,0 +1,111 @@ +-- Testbench automatically generated online +-- at http://vhdl.lapinoo.net +-- Generation date : 25.2.2018 11:52:20 GMT + +library ieee; +use ieee.std_logic_1164.all; + +entity Principal_tb is +end Principal_tb; + +architecture tb of Principal_tb is + + component Principal + port (CLK : in std_logic; + BTN : in std_logic; + IO : inout std_logic_vector (21 downto 20); + LED : out std_logic_vector (3 downto 0); + AN : out std_logic_vector (3 downto 0); + A_TO_G : out std_logic_vector (6 downto 0); + DOT : out std_logic); + end component; + + signal CLK : std_logic; + signal BTN : std_logic; + signal IO : std_logic_vector (21 downto 20); + signal LED : std_logic_vector (3 downto 0); + signal AN : std_logic_vector (3 downto 0); + signal A_TO_G : std_logic_vector (6 downto 0); + signal DOT : std_logic; + + constant TbPeriod : time := 20 ns; + signal TbClock : std_logic := '0'; + signal TbSimEnded : std_logic := '0'; + + constant BaudPeriod : time := 104167 ns; -- 9600 baud + constant CharacterPeriod : time := 10 * BaudPeriod; + signal rx : std_logic; + signal tx : std_logic; +begin + + dut : Principal + port map (CLK => CLK, + BTN => BTN, + IO => IO, + LED => LED, + AN => AN, + A_TO_G => A_TO_G, + DOT => DOT); + + -- Clock generation + TbClock <= not TbClock after TbPeriod/2 when TbSimEnded /= '1' else '0'; + + CLK <= TbClock; + + IO(20) <= rx; + tx <= IO(21); + + + stimuli : process + variable sending : std_logic_vector(7 downto 0); + begin + rx <= '1'; + + -- Reset generation + BTN <= '1'; + wait for 100 ns; + BTN <= '0'; + wait for 100 ns; + + wait for 2 * BaudPeriod; + + -- Send 'P' + rx <= '0'; -- Start bit + sending := x"50"; -- 'P' + wait for BaudPeriod; + for I in 0 to 7 loop + rx <= sending(I); + wait for BaudPeriod; + end loop; + rx <= '1'; -- Stop bit + wait for BaudPeriod; + + -- Wait for 1 byte receive + wait for CharacterPeriod; + + -- Wait margin + wait for 2 * BaudPeriod; + + -- Send '?' + rx <= '0'; -- Start bit + sending := x"3F"; -- '?' + wait for BaudPeriod; + for I in 0 to 7 loop + rx <= sending(I); + wait for BaudPeriod; + end loop; + rx <= '1'; -- Stop bit + wait for BaudPeriod; + + -- Wait for 2 bytes receive + wait for 2 * CharacterPeriod; + + -- Wait margin + wait for 2 * BaudPeriod; + + -- Stop the clock and hence terminate the simulation + TbSimEnded <= '1'; + wait; + end process; + +end tb; diff --git a/fpga/communication.vhd b/fpga/communication.vhd new file mode 100644 index 0000000..5810b2c --- /dev/null +++ b/fpga/communication.vhd @@ -0,0 +1,95 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + + +entity communication is + Port ( + clock : in std_logic; + reset : in std_logic; + left : in integer; + right : in integer; + front : in integer; + back : in integer; + txData : out std_logic_vector(7 downto 0); + txStb : out std_logic; + txAck : in std_logic; + rxData : in std_logic_vector(7 downto 0); + rxStb : in std_logic + ); +end communication; + +architecture Behavioral of communication is + + constant A2FD_PING : std_logic_vector(7 downto 0) := x"50"; -- 'P' + constant A2FD_RESETCODER : std_logic_vector(7 downto 0) := x"52"; -- 'R' + constant F2AD_ERR : std_logic_vector(7 downto 0) := x"45"; -- 'E' + constant ERR_UNKNOWN_CODE : std_logic_vector(7 downto 0) := x"43"; -- 'C' + constant F2AI_CODER : std_logic_vector(7 downto 0) := x"44"; -- 'D' + constant F2AI_CAPT : std_logic_vector(7 downto 0) := x"43"; -- 'C' + constant F2AT_CAPT : std_logic_vector(7 downto 0) := x"63"; -- 'c' + + type readStates is (readIdle); + signal readState : readStates := readIdle; + signal readOffset : integer := 0; + + type sendMessages is (none, A2FD_PINGs, F2AD_ERR_UNKNOWN_CODEs); + signal sendMessage : sendMessages := none; + signal sendOffset : integer := 0; + + signal frontTrigger : integer := 0; + signal backTrigger : integer := 0; + + signal txStbs : std_logic := '0'; + +begin + + txStb <= txStbs; + + readsendFA : process(clock, reset) + begin + if reset = '1' then + readState <= readIdle; + txStbs <= '0'; + sendMessage <= none; + sendOffset <= 0; + else + if rising_edge(clock) then + -- If read something + if rxStb = '1' then + if readState = readIdle then + case rxData is + when A2FD_PING => + sendMessage <= A2FD_PINGs; -- TODO Not so brutal + when others => + sendMessage <= F2AD_ERR_UNKNOWN_CODEs; + end case; + end if; + end if; + + -- If what was sent is acknowledged and there is still something to send + if txStbs = '0' or txAck = '1' then + txStbs <= '1'; + sendOffset <= sendOffset + 1; + case sendMessage is + when none => + txStbs <= '0'; + sendOffset <= 0; + when A2FD_PINGs => + txData <= A2FD_PING; + sendMessage <= none; + when F2AD_ERR_UNKNOWN_CODEs => + case sendOffset is + when 0 => + txData <= F2AD_ERR; + when others => + txData <= ERR_UNKNOWN_CODE; + sendMessage <= none; + end case; + end case; + end if; + end if; + end if; + end process; + +end Behavioral; diff --git a/fpga/communication_tb.gtkw b/fpga/communication_tb.gtkw new file mode 100644 index 0000000..4707e3b --- /dev/null +++ b/fpga/communication_tb.gtkw @@ -0,0 +1,41 @@ +[*] +[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI +[*] Sun Feb 25 17:14:08 2018 +[*] +[dumpfile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/build/communication_tb.vcd" +[dumpfile_mtime] "Sun Feb 25 17:12:53 2018" +[dumpfile_size] 4479 +[savefile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/communication_tb.gtkw" +[timestart] 0 +[size] 1680 1012 +[pos] -1 -1 +*-27.785210 1133000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[sst_width] 213 +[signals_width] 118 +[sst_expanded] 1 +[sst_vpaned_height] 244 +@28 +clock +reset +@820 +[color] 2 +rxdata[7:0] +@22 +[color] 2 +rxdata[7:0] +@28 +[color] 2 +rxstb +@820 +[color] 5 +txdata[7:0] +@22 +[color] 5 +txdata[7:0] +@28 +[color] 5 +txstb +[color] 5 +txack +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/fpga/communication_tb.vhd b/fpga/communication_tb.vhd new file mode 100644 index 0000000..0c25fbc --- /dev/null +++ b/fpga/communication_tb.vhd @@ -0,0 +1,139 @@ +-- Testbench automatically generated online +-- at http://vhdl.lapinoo.net +-- Generation date : 24.2.2018 16:12:08 GMT + +library ieee; +use ieee.std_logic_1164.all; + +entity communication_tb is +end communication_tb; + +architecture tb of communication_tb is + + component communication + port (clock : in std_logic; + reset : in std_logic; + left : in integer; + right : in integer; + front : in integer; + back : in integer; + txData : out std_logic_vector (7 downto 0); + txStb : out std_logic; + txAck : in std_logic; + rxData : in std_logic_vector (7 downto 0); + rxStb : in std_logic); + end component; + + signal clock : std_logic; + signal reset : std_logic; + signal left : integer; + signal right : integer; + signal front : integer; + signal back : integer; + signal txData : std_logic_vector (7 downto 0); + signal txStb : std_logic; + signal txAck : std_logic; + signal rxData : std_logic_vector (7 downto 0); + signal rxStb : std_logic; + + constant TbPeriod : time := 20 ns; + signal TbClock : std_logic := '0'; + signal TbSimEnded : std_logic := '0'; + +begin + + dut : communication + port map (clock => clock, + reset => reset, + left => left, + right => right, + front => front, + back => back, + txData => txData, + txStb => txStb, + txAck => txAck, + rxData => rxData, + rxStb => rxStb); + + -- Clock generation + TbClock <= not TbClock after TbPeriod/2 when TbSimEnded /= '1' else '0'; + + clock <= TbClock; + + stimuli : process + begin + left <= 0; + right <= 0; + front <= 0; + back <= 0; + txAck <= '0'; + rxData <= (others => '0'); + rxStb <= '0'; + + -- Reset generation + reset <= '1'; + wait for 100 ns; + reset <= '0'; + wait for 100 ns; + + + -- Test Ping + report "Receiving 'P'" severity note; + rxData <= x"50"; + rxStb <= '1'; + wait for TbPeriod; + rxStb <= '0'; + + wait for 100 ns; + assert txData = x"50" report "Not sent 'P'" severity error; + assert txStb = '1' report "Not sending" severity error; + + report "Acknowledging send" severity note; + wait for 100 ns; + txAck <= '1'; + wait for TbPeriod; + txAck <= '0'; + + wait for 100 ns; + assert txStb = '0' report "Not stopping send" severity error; + + wait for 100 ns; -- Margin + + + -- Test unknown char + report "Receiving '?'" severity note; + rxData <= x"3F"; + rxStb <= '1'; + wait for TbPeriod; + rxStb <= '0'; + + wait for 100 ns; + assert txData = x"45" report "Not sent 'E'" severity error; + assert txStb = '1' report "Not sending" severity error; + + report "Acknowledging send" severity note; + wait for 100 ns; + txAck <= '1'; + wait for TbPeriod; + txAck <= '0'; + + wait for 100 ns; + assert txData = x"43" report "Not sent 'C'" severity error; + assert txStb = '1' report "Not sending" severity error; + + report "Acknowledging send" severity note; + wait for 100 ns; + txAck <= '1'; + wait for TbPeriod; + txAck <= '0'; + + wait for 100 ns; + assert txStb = '0' report "Not stopping send" severity error; + wait for 100 ns; -- Margin + + + TbSimEnded <= '1'; + wait; + end process; + +end tb; diff --git a/fpga/hcSr04.vhd b/fpga/hcSr04.vhd index a6f5a2b..e09724b 100644 --- a/fpga/hcSr04.vhd +++ b/fpga/hcSr04.vhd @@ -1,6 +1,5 @@ LIBRARY ieee; USE ieee.std_logic_1164.all; -USE ieee.std_logic_unsigned.all; ENTITY hcSr04 IS GENERIC( diff --git a/fpga/hcSr04Fulldiv.vhd b/fpga/hcSr04Fulldiv.vhd deleted file mode 100644 index 0bb9514..0000000 --- a/fpga/hcSr04Fulldiv.vhd +++ /dev/null @@ -1,69 +0,0 @@ -LIBRARY ieee; -USE ieee.std_logic_1164.all; -USE ieee.std_logic_unsigned.all; -USE ieee.std_logic_arith.all; - -ENTITY hcSr04 IS - GENERIC( - fFpga : INTEGER := 50_000_000; -- frequency of the FPGA clock (Hz) - maxOutput : INTEGER := 65535 -- maximum number to store the distance - ); -PORT( - clk : IN STD_LOGIC; -- clock of the FPGA - echo : IN STD_LOGIC; -- echo pin of the hcSr04 - distance : OUT INTEGER RANGE 0 TO maxOutput; -- Ranges from 0 to 4 meters, 0 if no data - trigger : OUT STD_LOGIC; -- trigger pin of the hcSr04 - start : IN STD_LOGIC; -- Set to '1' everytime a measurement is needed (or keep at '1' for continuous measurement) - finished : OUT STD_LOGIC -- Driven to '1' everytime a measurement has finished - ); -END hcSr04; - -ARCHITECTURE Behavioral OF hcSr04 IS - CONSTANT triggerTicks : INTEGER := fFPGA / 100000; -- Number of FPGA ticks that makes 10us (used for trigger) - CONSTANT measurementTicks : INTEGER := fFPGA / 17; -- Number of FPGA ticks that makes 60ms (used for measurement cycles) - CONSTANT maximumRange : INTEGER := 4; -- Maximum range the sensor can detect - CONSTANT distanceTicks : INTEGER := maximumRange * fFPGA / 172; -- Number of FPGA ticks that makes the maximum distance that can be measured - -- 172 = 1 / 58 s/m - SIGNAL measurementCounter : INTEGER RANGE 0 to measurementTicks - 1 := 0; -- Progress in the measurement - SIGNAL distanceCounter : INTEGER RANGE 0 to distanceTicks - 1 := 0; -- Ticks for wich echo has been at one - SIGNAL triggerCounter : INTEGER RANGE 0 to triggerTicks - 1 := 0; -- Progress in the trigger - TYPE stateType IS (init, waiting, triggering, measuring); - SIGNAL state : stateType; -BEGIN - measure : process(clk) - begin - if rising_edge(clk) then - CASE state IS - WHEN init => - trigger <= '0'; - distance <= 0; - state <= waiting; - WHEN waiting => - finished <= '0'; - IF start = '1' THEN - trigger <= '1'; - triggerCounter <= 0; - state <= triggering; - END IF; - WHEN triggering => - triggerCounter <= triggerCounter + 1; - IF triggerCounter = triggerTicks - 1 THEN - trigger <= '0'; - measurementCounter <= 0; - distanceCounter <= 0; - state <= measuring; - END IF; - WHEN measuring => - IF echo = '1' and distanceCounter < distanceTicks THEN - distanceCounter <= distanceCounter + 1; - END IF; - measurementCounter <= measurementCounter + 1; - IF measurementCounter = measurementTicks - 1 THEN - distance <= distanceCounter * maxOutput / distanceTicks; - finished <= '1'; - state <= waiting; - END IF; - END CASE; - end if; - end process; -END Behavioral; diff --git a/fpga/hedm.vhd b/fpga/hedm.vhd index 08baf13..c2127ed 100644 --- a/fpga/hedm.vhd +++ b/fpga/hedm.vhd @@ -39,9 +39,9 @@ begin An <= chA; Bn <= chB; - -- On pourrait optimiser la logique avec un tableau de Karnaugh ou autres méthodes - -- de simplification d'algèbre de Boole, mais le "compilateur" pour FPGA fera un - -- tout aussi bon travail, on garde donc le code suivant pour la lisibilité + -- On pourrait optimiser la logique avec un tableau de Karnaugh ou autres méthodes + -- de simplification d'algèbre de Boole, mais le synthétiseur pour FPGA fera un + -- tout aussi bon travail, on garde donc le code suivant pour la lisibilité if (Ap = '0' and An = '1') then -- Front montant A if (Bn = '0') then diff --git a/fpga/project.cfg b/fpga/project.cfg index 119cd88..b10ce91 100644 --- a/fpga/project.cfg +++ b/fpga/project.cfg @@ -8,7 +8,7 @@ TOPLEVEL = Principal # VHDSOURCE = $(TOPLEVEL).vhd uart.vhd # CONSTRAINTS = mercury.ucf # Debug -VHDSOURCE = $(TOPLEVEL).vhd $(wildcard *.vhd) +VHDSOURCE = $(TOPLEVEL).vhd $(filter-out %_tb.vhd,$(wildcard *.vhd)) CONSTRAINTS = debug.ucf