1
0
Fork 0
mirror of https://github.com/RobotechLille/cdf2018-principal synced 2024-11-14 04:16:05 +01:00

FPGA : Communication sur plusieurs octets

This commit is contained in:
Geoffrey Frogeye 2018-02-24 18:16:09 +01:00
parent 9a2bf3d9cd
commit 81a7fd8bd7
10 changed files with 489 additions and 128 deletions

View file

@ -1,5 +1,6 @@
library IEEE; library IEEE;
use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Principal is entity Principal is
@ -17,8 +18,8 @@ end Principal;
architecture Behavioral of Principal is architecture Behavioral of Principal is
-- Blink led -- Blink led
signal pulse : std_logic := '0';
signal count : integer := 0; signal count : integer := 0;
signal theled: std_logic_vector(3 downto 0) := "0000";
-- General -- General
signal reset : std_logic := '0'; signal reset : std_logic := '0';
@ -30,8 +31,6 @@ architecture Behavioral of Principal is
-- Sensors -- Sensors
signal front : integer; signal front : integer;
signal back : integer; signal back : integer;
signal frontTrigger : integer := 0;
signal backTrigger : integer := 0;
-- AF -- AF
component uart is component uart is
@ -61,16 +60,22 @@ architecture Behavioral of Principal is
signal rxData : std_logic_vector(7 downto 0); signal rxData : std_logic_vector(7 downto 0);
signal rxStb : std_logic := '0'; signal rxStb : std_logic := '0';
constant A2FD_PING : std_logic_vector := x"50"; -- 'P' -- Handling
component communication is
type readStates is (readIdle); Port (
signal readState : readStates := readIdle; clock : in std_logic;
reset : in std_logic;
type sendMessages is (none, A2FD_PINGs); left : in integer;
signal resetSendMessageRead : std_logic := '0'; right : in integer;
signal resetSendMessageSend : std_logic := '0'; front : in integer;
signal sendMessage : sendMessages := none; back : in integer;
signal sendOffset : integer := 0; 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 -- Debug
component sevenseg is component sevenseg is
@ -100,63 +105,41 @@ begin
rx => IO(20) rx => IO(20)
); );
readsendFA : process(reset, rxStb, txAck) com: communication port map(
begin clock => CLK,
if reset = '1' then reset => reset,
readState <= readIdle; left => left,
sendMessage <= none; right => right,
txStb <= '0'; front => front,
sendOffset <= 0; back => back,
else txData => txData,
-- If read something txStb => txStb,
if rxStb = '1' then txAck => txAck,
if readState = readIdle then rxData => rxData,
case rxData is rxStb => rxStb
when A2FD_PING => -- 'P' );
sendMessage <= A2FD_PINGs; -- TODO Not so brutal
when others =>
end case;
end if;
end if;
-- 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 -- Debug
blinkled : process(CLK, reset) blinkled : process(CLK, reset)
begin begin
if reset = '1' then if reset = '1' then
count <= 0; count <= 0;
pulse <= '0'; theled <= "0000";
elsif CLK'event and CLK = '1' then elsif CLK'event and CLK = '1' then
if count = 9999999 then if count = 9999999 then
count <= 0; count <= 0;
pulse <= not pulse; theled(3) <= not theled(3);
theled(2 downto 0) <= "000";
else else
count <= count + 1; count <= count + 1;
theled(2 downto 0) <= theled(2 downto 0) or (txStb & rxStb & txAck);
end if; end if;
end if; end if;
end process; end process;
LED(3) <= pulse;
LED(2) <= txStb; LED <= theled;
LED(1) <= rxStb;
LED(0) <= txAck;
debugSeg: sevenseg port map( debugSeg: sevenseg port map(
data => sevensegdata, data => sevensegdata,

62
fpga/Principal_tb.gtkw Normal file
View file

@ -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

111
fpga/Principal_tb.vhd Normal file
View file

@ -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;

95
fpga/communication.vhd Normal file
View file

@ -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;

View file

@ -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

139
fpga/communication_tb.vhd Normal file
View file

@ -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;

View file

@ -1,6 +1,5 @@
LIBRARY ieee; LIBRARY ieee;
USE ieee.std_logic_1164.all; USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY hcSr04 IS ENTITY hcSr04 IS
GENERIC( GENERIC(

View file

@ -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;

View file

@ -39,9 +39,9 @@ begin
An <= chA; An <= chA;
Bn <= chB; Bn <= chB;
-- On pourrait optimiser la logique avec un tableau de Karnaugh ou autres méthodes -- 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 -- 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é -- tout aussi bon travail, on garde donc le code suivant pour la lisibilité
if (Ap = '0' and An = '1') then -- Front montant A if (Ap = '0' and An = '1') then -- Front montant A
if (Bn = '0') then if (Bn = '0') then

View file

@ -8,7 +8,7 @@ TOPLEVEL = Principal
# VHDSOURCE = $(TOPLEVEL).vhd uart.vhd # VHDSOURCE = $(TOPLEVEL).vhd uart.vhd
# CONSTRAINTS = mercury.ucf # CONSTRAINTS = mercury.ucf
# Debug # Debug
VHDSOURCE = $(TOPLEVEL).vhd $(wildcard *.vhd) VHDSOURCE = $(TOPLEVEL).vhd $(filter-out %_tb.vhd,$(wildcard *.vhd))
CONSTRAINTS = debug.ucf CONSTRAINTS = debug.ucf