From 39154e4f5ee39fcd17064fa0547c1d6dfeb60172 Mon Sep 17 00:00:00 2001 From: Geoffrey Frogeye Date: Sat, 24 Feb 2018 16:56:57 +0100 Subject: [PATCH] FPGA: Ajout de simulations --- fpga/Makefile | 20 ++++++- fpga/generateConstants.sh | 12 +++++ fpga/hedm.vhd | 23 +++++--- fpga/hedm_tb.gtkw | 25 +++++++++ fpga/hedm_tb.vhd | 110 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+), 9 deletions(-) create mode 100755 fpga/generateConstants.sh create mode 100644 fpga/hedm_tb.gtkw create mode 100644 fpga/hedm_tb.vhd diff --git a/fpga/Makefile b/fpga/Makefile index 2df7466..3614648 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -87,7 +87,7 @@ export XILINX default: $(BITFILE) clean: - rm -rf build + rm -rf build/* build/$(PROJECT).prj: project.cfg @echo "Updating $@" @@ -159,6 +159,24 @@ isimgui: build/isim_$(TB)$(EXE) @echo "run all" >> build/isim_$(TB).cmd cd build ; ./isim_$(TB)$(EXE) -gui -tclbatch isim_$(TB).cmd +########################################################################### +# Testing (using ghdl and gtkwave) +########################################################################### + +%_syntax: %.vhd + ghdl -s --mb-comments "$<" + +build/%.o: %.vhd + ghdl -a --mb-comments --workdir="$(shell dirname "$@")" "$<" + +build/%_tb: build/%_tb.o $(addprefix build/,$(subst .vhd,.o,$(VHDSOURCE))) + ghdl -e --workdir="$(shell dirname "$@")" -o "$@" "$(basename $(notdir $<))" + +build/%_tb.vcd: build/%_tb + (cd "$(shell dirname "$<")"; ghdl -r "$(basename $(notdir $<))" --vcd="../$@" ) + +%_wave: build/%_tb.vcd + gtkwave --save "$(notdir $(basename $<)).gtkw" "$<" ########################################################################### # Programming diff --git a/fpga/generateConstants.sh b/fpga/generateConstants.sh new file mode 100755 index 0000000..73c651a --- /dev/null +++ b/fpga/generateConstants.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +cd "$(dirname "${BASH_SOURCE[0]}")" + +grep "#define [A-Z0-9_]\+ '[a-zA-Z]'" ../arduino/AFsignals.h | while read line +do + name="$(echo "$line" | cut -d ' ' -f 2)" + letter="$(echo "$line" | cut -d ' ' -f 3 | cut -d "'" -f 2)" + hex="$(python -c "print(hex(ord('$letter'))[2:])")" + + echo " constant $name : std_logic_vector(7 downto 0) := x\"$hex\"; -- '$letter'" +done diff --git a/fpga/hedm.vhd b/fpga/hedm.vhd index 1f52bd8..08baf13 100644 --- a/fpga/hedm.vhd +++ b/fpga/hedm.vhd @@ -13,18 +13,25 @@ entity hedm is clk : in STD_LOGIC; -- Horloge, la fréquence n'importe pas chA : in STD_LOGIC; -- Canal A chB : in STD_LOGIC; -- Canal B + reset : in STD_LOGIC; counts : out integer ); end hedm; architecture Behavioral of hedm is - signal counter : integer; - signal An, Bn : STD_LOGIC; -- Nouvelles valeurs de A et B stockées pour que les entrées soient lues une seule fois en début de cycle - signal Ap, Bp : STD_LOGIC; -- Précédentes valeurs de A et B pour détecter les front montant + signal counter : integer := 0; + signal An, Bn : STD_LOGIC := '0'; -- Nouvelles valeurs de A et B stockées pour que les entrées soient lues une seule fois en début de cycle + signal Ap, Bp : STD_LOGIC := '0'; -- Précédentes valeurs de A et B pour détecter les front montant begin - processInput : process(clk) + processInput : process(clk, reset) begin - if rising_edge(clk) then + if reset = '1' then + counter <= 0; + An <= '0'; + Bn <= '0'; + Ap <= '0'; + Bp <= '0'; + elsif rising_edge(clk) then Ap <= An; Bp <= Bn; @@ -32,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 "compilateur" 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/hedm_tb.gtkw b/fpga/hedm_tb.gtkw new file mode 100644 index 0000000..7e953ae --- /dev/null +++ b/fpga/hedm_tb.gtkw @@ -0,0 +1,25 @@ +[*] +[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI +[*] Sat Feb 24 16:20:02 2018 +[*] +[dumpfile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/build/hedm_tb.vcd" +[dumpfile_mtime] "Sat Feb 24 16:19:31 2018" +[dumpfile_size] 10717 +[savefile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/build/hedm_tb.gtkw" +[timestart] 0 +[size] 1600 862 +[pos] -1 -1 +*-28.000000 -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 -1 +[sst_width] 213 +[signals_width] 78 +[sst_expanded] 1 +[sst_vpaned_height] 244 +@28 +clk +reset +cha +chb +@421 +counts +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/fpga/hedm_tb.vhd b/fpga/hedm_tb.vhd new file mode 100644 index 0000000..e2f6b17 --- /dev/null +++ b/fpga/hedm_tb.vhd @@ -0,0 +1,110 @@ +-- Testbench automatically generated online +-- at http://vhdl.lapinoo.net +-- Generation date : 24.2.2018 15:15:56 GMT + +library ieee; +use ieee.std_logic_1164.all; + +entity hedm_tb is + end hedm_tb; + +architecture tb of hedm_tb is + + component hedm + port (clk : in std_logic; + chA : in std_logic; + chB : in std_logic; + reset : in std_logic; + counts : out integer); + end component; + + signal clk : std_logic; + signal chA : std_logic; + signal chB : std_logic; + signal reset : std_logic; + signal counts : integer; + + constant TbPeriod : time := 20 ns; + signal TbClock : std_logic := '0'; + signal TbSimEnded : std_logic := '0'; + +begin + + dut : hedm + port map (clk => clk, + chA => chA, + chB => chB, + reset => reset, + counts => counts); + + -- Clock generation + TbClock <= not TbClock after TbPeriod/2 when TbSimEnded /= '1' else '0'; + + clk <= TbClock; + + stimuli : process + variable tour : integer; + constant nbTours : integer := 10; + begin + chA <= '0'; + chB <= '0'; + + -- Reset generation + reset <= '1'; + wait for 100 ns; + reset <= '0'; + wait for 100 ns; + + -- Test sens avant + for I in 0 to nbTours-1 loop + chA <= '1'; + wait for TbPeriod; + chB <= '1'; + wait for TbPeriod; + chA <= '0'; + wait for TbPeriod; + chB <= '0'; + wait for TbPeriod; + end loop; + + wait for 5 * TbPeriod; + assert counts = nbTours * 4 report "Sens avant faux, reçu " & integer'image(counts) severity error; + + + -- Test sens avant + for I in 0 to nbTours-1 loop + chB <= '1'; + wait for TbPeriod; + chA <= '1'; + wait for TbPeriod; + chB <= '0'; + wait for TbPeriod; + chA <= '0'; + wait for TbPeriod; + end loop; + + wait for 5 * TbPeriod; + assert counts = 0 report "Sens arrière faux, reçu " & integer'image(counts) severity error; + + -- Test aller-retours + for I in 0 to nbTours-1 loop + chA <= '1'; + wait for TbPeriod; + chB <= '1'; + wait for TbPeriod; + chB <= '0'; + wait for TbPeriod; + chA <= '0'; + wait for TbPeriod; + end loop; + + wait for 5 * TbPeriod; + assert counts = 0 report "Aller-retours faux, reçu " & integer'image(counts) severity error; + + + -- Stop the clock and hence terminate the simulation + TbSimEnded <= '1'; + wait; + end process; + +end tb;