Projet électronique FPGA #9 : Calcul de la factorielle de n: Implémentation sur carte FPGA

Projet FPGA Calcul de Factorielle n logarithme de factorielle - factorielle de 0

Objectifs du projet :

  • Savoir comment calculer la factorielle de 0 ?
  • Savoir comment maintenir les données en mémoire dans le bus de sortie ?
  • Savoir comment synchroniser les données à l’entrée ?
  • Savoir implémenter la fonction de saturation en VHDL
  • Implémentation sur carte du projet

Analyse de fonctionnement

Comment calculer la factorielle de 0 ?

Dans ce projet on va s’intéresser aux aspects pratiques du code VHDL illustrés dans le projet 7. Comme vous constatez dans le projet 7, la factorielle de 0 n’est pas implémentée ! Je m’en suis rendu compte durant les tests sur carte du composant. Souvent en électronique, on fait des allers-retours entre l’étape de développement et implémentation pour but d’obtenir un fonctionnement optimal. En pratique, c’est rare que notre code marche au premier coup 🙂

Revenant à notre question, une solution possible est de tester la valeur de la donnée à l’entrer : Si elle est nulle on remplace la valeur nulle par 1 et on maintient la valeur dans le cas contraire.

if D_in=b"00000" then
        D_in_tmp <= b"00001";
else
        D_in_tmp<= D_in;
end if;

La donnée dans le bus de sortie D_out dure un coup d’horloge, la sortie passe à 1 dans le prochain coup d’horloge. D’une autre façon, le résultat dans le bus de sortie D_out bascule entre ‘1’ et D_in! (voir image ci-dessous) Ce fonctionnement peut être indésirable si on cherche une donnée stable tant que la donnée à l’entrée reste inchangée. L’avantage du fonctionnement mémoire est d’assurer que la donnée soit lisible et acquise correctement par le composant en amant.

Projet FPGA Calcul de Factorielle n logarithme de factorielle - simulation 6

L’implémentation de la fonction mémoire peut être réalisée à l’instant de la détection du front montant du signal D_outReady, dalleur ce dernier passe à 1 au même temps que la donnée soit présente dans le bus de sortie.  L’approche consiste la mise à jour de la donnée de sortie uniquement durant le front montant du signal D_outReady.

Comme vous l’avez constaté, le bus de sortie est sur 123 bits pour une entrée sur 5 bits. Dans la partie implémentation on va s’intéresser uniquement par les 8 premiers bits du bus de sortie à cause de limitation de notre des LED dans notre kit de développement. Ce choix impose que la sortie D_out ne puisse prendre que des valeurs inférieures ou égales à 255 (1111 1111). D’une autre manière on ne peut calculer que les factorielles des valeurs suivantes : 0, 1, 2, 3 et 4. La factorielle de 6 != 720 >255. La fonction de saturation sera active pour des valeurs en entrée allant de 6 à 31. On a choisi 255 (FF) comme valeur de saturation. La figure ci-dessous illustre la fonction du transfert du composant menu de la fonction de saturation et le code Matlab correspondant:

Implémentation FPGA Calcul de Factorielle n logarithme de factorielle - saturation

Code matlab
clear all; close all; clc

% D_in
N=5;
D_in=0:2^N-1;

% D_out
D_out_tmp=factorial(D_in);
D_out=zeros(1,length(D_in));

for i=1:length(D_in)
    if D_out_tmp(i)>=255
        D_out(i)=255;
    else
        D_out(i)=D_out_tmp(i);
    end;
end

% Affichage
figure(1);
plot(D_in,D_out); grid on; hold on
xlim([D_in(1) D_in(end)]);
ylim([D_out(1) D_out(end)+10]);
xlabel('D_{in}(1..31)');
ylabel('D_{out}(1..255)');

Extrait du code VHDL de la fonction de mémorisation et de saturation :

...
if D_outReady_tmp='1' then
        if D_out_tmp > x"000000000000000000000000008" & b"00000" then  -- 256
                D_out <= x"FF";
        else
                D_out <= D_out_tmp(P-1 downto 0);
        end if;
end if;
...

Code VHDL (FactorielMem.vhd):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;



entity FactorielMem is
        Generic ( N : positive := 108;
                  M : positive := 5;
                      P : positive := 8
                        );
    Port ( Rst                         : in  STD_LOGIC;
           Clk                         : in  STD_LOGIC;
           D_in                 : in  STD_LOGIC_VECTOR (M-1 downto 0);
           D_out_Ready                 : out  STD_LOGIC;
           D_out                 : out  STD_LOGIC_VECTOR (P-1 downto 0));
end FactorielMem;

architecture Behavioral of FactorielMem is

signal D_outReady_tmp         :   STD_LOGIC :='0';
signal D_out_tmp         :   STD_LOGIC_VECTOR (N+M-1 downto 0):=x"000000000000000000000000000" & b"00001";
signal D_in_tmp         :   STD_LOGIC_VECTOR (M-1 downto 0):=b"00001";

COMPONENT FactorielN
PORT(
        Rst : IN std_logic;
        Clk : IN std_logic;
        D_in : IN std_logic_vector(M-1 downto 0);
        D_out_Ready : OUT std_logic;
        D_out : OUT std_logic_vector(N+M-1 downto 0)
        );
END COMPONENT;

begin

        FAC5: FactorielN PORT MAP(
                Rst => Rst,
                Clk => Clk,
                D_in => D_in_tmp,
                D_out_Ready => D_outReady_tmp,
                D_out => D_out_tmp
        );

        -- Memorisation de la sortie + Gestion de 0!
        P_data_out : process(Rst, Clk, D_outReady_tmp)
        begin
                if Rst ='1' then
                        D_out(P-1 downto 1) <=(others =>'0');
                        D_out(0) <= '1';
                elsif Clk = '1' and Clk'event then
                        -- 0!=1
                        if D_in=b"00000" then
                                D_in_tmp <= b"00001";
                        else
                                D_in_tmp<= D_in;
                        end if;
                        -- Saturation de la sortie
                        if D_outReady_tmp='1' then
                                if D_out_tmp > x"000000000000000000000000008" & b"00000" then  -- 256
                                        D_out <= x"FF";
                                else
                                        D_out <= D_out_tmp(P-1 downto 0);
                                end if;
                        end if;
                end if;
        end process;
        D_out_Ready <=D_outReady_tmp;
end Behavioral;

Code VHDL du fichier de simulation (tb_FactorielMem.vhd):

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std;

ENTITY tb_FactorielMem IS
END tb_FactorielMem;

ARCHITECTURE behavior OF tb_FactorielMem IS

        -- Component Declaration for the Unit Under Test (UUT)
        COMPONENT FactorielMem
        PORT(
                Rst : IN  std_logic;
                Clk : IN  std_logic;
                D_in : IN  std_logic_vector(4 downto 0);
                D_out_Ready : OUT  std_logic;
                D_out : OUT  std_logic_vector(7 downto 0)
                );
        END COMPONENT;


        --Inputs
        signal Rst : std_logic := '1';
        signal Clk : std_logic := '0';
        signal D_in : std_logic_vector(4 downto 0) := b"00001";

        --Outputs
        signal D_out_Ready : std_logic;
        signal D_out : std_logic_vector(7 downto 0);

        -- Clock period definitions
        constant Clk_period : time := 10 ns;

BEGIN

        -- Instantiate the Unit Under Test (UUT)
        uut: FactorielMem PORT MAP (
                Rst => Rst,
                Clk => Clk,
                D_in => D_in,
                D_out_Ready => D_out_Ready,
                D_out => D_out
                );

        -- Clock process definitions
        Clk_process :process
        begin
                Clk <= '0';
                wait for Clk_period/2;
                Clk <= '1';
                wait for Clk_period/2;
        end process;

        -- Rst process definitions
        Rst_process :process
        begin
                Rst <= '1';
                wait for Clk_period;

                Rst <= '0';
                wait for 200*Clk_period;
        end process;

        -- Input Data process definitions
        D_in_process :process
        begin
                D_in <= D_in+1;
                wait for 50*Clk_period;
        end process;
END;

Résultats de simulation:

Implémentation FPGA Calcul de Factorielle n logarithme de factorielle - simulation 2

Implémentation FPGA Calcul de Factorielle n logarithme de factorielle - simulation 1

Pinout du composant (pinout_FactorielMem.ucf) :

# Alimentation
CONFIG VCCAUX = "3.3" ;

# Horloge 12 MHz
NET "Clk"                     LOC = P129  | IOSTANDARD = LVCMOS33 | PERIOD = 12MHz;

# Entees: Rst + D_in
NET "Rst"                     LOC = P70   | PULLUP  | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_in[0]"                 LOC = P69   | PULLUP  | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_in[1]"                 LOC = P68   | PULLUP  | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_in[2]"                 LOC = P64   | PULLUP  | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_in[3]"                 LOC = P63   | PULLUP  | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_in[4]"                 LOC = P60   | PULLUP  | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;

# Sortie D_out_Ready
NET "D_out_Ready"            LOC = P19   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;

# Sortie D_out
NET "D_out[0]"                LOC = P46   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_out[1]"                LOC = P47   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_out[2]"                LOC = P48   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_out[3]"                LOC = P49   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_out[4]"                LOC = P50   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_out[5]"                LOC = P51   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_out[6]"                LOC = P54   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;
NET "D_out[7]"                LOC = P55   | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12;

 

Implémentation FPGA Calcul de Factorielle n logarithme de factorielle - factorielle 0 cablage

Photos du projet:

Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 2 Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 2
Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 4 Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 4
Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 3 Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 3
Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 5 Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 5
Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 6 Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 6
Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 15 Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 15
Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 31 Implémentation FPGA Calcul de Factorielle n logarithme de factorielle -factorielle 31
Implémentation FPGA Calcul de Factorielle n logarithme de factorielle - Valeurs Implémentation FPGA Calcul de Factorielle n logarithme de factorielle - Valeurs

Vidéo illustrative:

************

Un petit commentaire de vous, un Grand encouragement pour nous 🙂

************

Téléchargement du projet

************

Articles

1 thought on “Projet électronique FPGA #9 : Calcul de la factorielle de n: Implémentation sur carte FPGA”

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Anti-Robot *