Les Processeurs Embarqués
I. Définition:
Un processeur embarqué est un microprocesseur (ou microcontrôleur) intégré dans un
système embarqué
processeur embarqué est :
• Soit déjà implanté dans le circuit électronique en « dur » : processeur matériel.
• Soit un bloc IP : processeur logiciel.
I.1 Le processeurs matériel (hardcore) est figée par le fabricant,
• On change le programme de la mémoire
• On peut aussi faire une configuration
Exemples de configuration :
Sur puce il peut y avoir plein de périphériques, mais on utilise
une partie
Configurer le débit du port série
Configurer des ports d'entrée-sortie
On trouve des processeurs matériels:
• Microcontrôleur STM32 (ARM cortex-M)
• Raspberry PI( ARM cortex-A)
• Processeur RISC-V sur FPGA :Ces processeurs Offrent de très
performances ( car il sont optimises au niveau transistor) mais
compliquent la structure du FPGA cad il augmente le cout de conception
et de validation du FPGA.
I.2 Un processeur logiciels (softcore):
Un processeur softcore est implémenté sur un système
reprogrammable comme un FPGA. On parle alors de « système
sur puce programmable » (System on Programmable Chip ou
SoPC).
On trouve des processeurs softcores :
– Le processeur Picoblaze et Microblaze de Xilinx.
– Le processeur NIOS et NIOS II d'Altera.
II. Microprocesseur PicoBlaze
II.1 Architecture
II.2 Exécution d’une instruction
II.3 Jeu d’instructions
1) instruction LOAD
• Il existe 16 registres de taille 8 bits: s0…sF
• Chargement d’une valeur constante dans un registre
• Copier le contenu d’un registre vers un autre
• L'instruction LOAD ne permet pas d'écrire ou de lire depuis la
mémoire.
• Les drapeaux C et Z ne sont pas affectés.
2) Jeu d’instructions : AND, OR, XOR
AND operande1 et destination,operande2
OR operande1 et destination,operande2
XOR operande1 et destination,operande2
Si Operande 2 est une constante
• AND[OR, XOR] sx,cte; sx AND cte => sx
Si Operande 2 est le contenu d'un registre
• AND[OR, XOR] sx,sy; sx AND sy => sx
Le drapeau C passe à zéro, le drapeau Z se position en focntion du
résultat.
• Exemple
LOAD S0,45
JUMP plus_bas
LOAD s1,87
…
Plus_bas: LOAD S4,12
• Le compilateur remplace chaque ligne par son code.
• Le premier code est rangé à l’adresse 0, le seconde à l’adresse 1, et
finalement le dernier « LOAD» à une adresse pas connu par le
programmeur, mais connu par le compilateur.
• Compilateur, remplacera l’étiquette « plus_bas » de la ligne « JUMP »
par l’adresse de la ligne « LOAD S4,12 »
3) Jeu d'instruction : OUTPUT
• Pour écrire une donnée sur un port spécifique
• Syntaxe:
output sx,pp écrire sur le port pp
output sx,(cy) écrire sur le port (cy)
• Interface du port de sortie
• Conception de Process de sortie
entity testPS is
Port ( portid : in STD_LOGIC_VECTOR (7 downto 0);
outports : in STD_LOGIC_VECTOR (7 downto 0);
write,clk : in STD_LOGIC;
p1 : out STD_LOGIC_VECTOR (7 downto 0);
p2 : out STD_LOGIC_VECTOR (7 downto 0);
p3 : out STD_LOGIC_VECTOR (7 downto 0));
end testPS;
architecture Behavioral of testPS is
begin
if portid=x"01" then
process(clk)
p2<=outports;
begin end if;
if clk'event and clk='1' then if portid=x"02" then
p3<=outports;
if write='1' then
end if;
if portid=x"00" then end if;
end if;
p1<=outports;
end process;
end if; end Behavioral;
• Programme testbench:
entity tbtestPS is
-- Port ( );
end tbtestPS;
architecture Behavioral of tbtestPS is
component testPS
port ( portid : in STD_LOGIC_VECTOR (7 downto 0);
outports : in STD_LOGIC_VECTOR (7 downto 0);
write,clk : in STD_LOGIC;
p1 : out STD_LOGIC_VECTOR (7 downto 0);
p2 : out STD_LOGIC_VECTOR (7 downto 0);
p3 : out STD_LOGIC_VECTOR (7 downto 0));
end component;
signal portid,outports,p1,p2,p3:STD_LOGIC_VECTOR (7 downto 0);
process
signal write,clk:STD_LOGIC; begin
portid<="00000000";
begin write<='0';
outports<="10000001"; wait for 20ns;
uut1: testPS port map (portid=> portid<="00000000";
portid,outports=> outports,write=> write<='1';
outports<="11111111"; wait for 40ns;
write,clk=>clk,p1=>p1,p2=>p2,p3=>p3); portid<="00000001";
write<='0';
process outports<="11111110"; wait for 20ns;
begin portid<="00000001";
write<='1';
clk <='0'; wait for 20ns; outports<="11111110"; wait for 40ns;
clk <='1' ;wait for 20ns; portid<="00000010";
write<='1';
end process; outports<="11111100"; wait for 40ns;
end process;
end Behavioral;
4) Jeu d'instruction: INPUT
• Pour lire une donnée sur un port spécifique
• Syntaxe:
input Sx,pp
input Sx,(Sy)
Interface du port d’entrée
Conception de Process d’entrée
Création d'un système (matériel et logiciel)
• Pour créer un système matériel et logiciel permettant de copier l'état
des interrupteurs (switches) vers les LED sur une carte FPGA à l'aide du
processeur PicoBlaze,
• L'architecture matérielle programmable la plus simple possible
implique un seul processeur (un PicroBlaze), et mémoire.
• Naturellement, une architecture matérielle programmable nécessite un
programme (logiciel: code assembleur ) pour fonctionner.
KCPSM6
• Le KCPSM6 (KiloCore PicoBlaze State Machine 6) est un microcontrôleur 8 bits
intégré développé par AMD pour être utilisé dans les FPGA de la série 7, tels que
les familles Virtex-7, Kintex-7, Artix-7, ainsi que les familles Zynq et UltraScale.
• Le KCPSM6 est un cœur de microcontrôleur léger et efficace, idéal pour les tâches
de contrôle embarqué dans des systèmes FPGA
• Le développement avec le KCPSM6 est facilité par l'utilisation de l'outil KCPSM6
Assembler, qui permet de convertir le code assembleur en un fichier de
configuration compatible avec les FPGA AMD.
• Le choix de circuit: xc7a35tcpg236-1
• Déclaration et instanciation du up et de la mémoire
• Ecrire le programme en assembleur
• Ajouter du up et de la mémoire au projet
• Ajouter du process de sortie
• Attribution des broches(xdc)
• Créer testbench
entity main is
Port ( clk : in STD_LOGIC;
sw : in STD_LOGIC_VECTOR (7 downto 0);
led : out STD_LOGIC_VECTOR (7 downto 0));
end main;
Déclaration et instanciation du up et de la mémoire
KCPSM6
Déclaration du up
component kcpsm6
generic( hwbuild : std_logic_vector(7 downto 0) := X"00";
interrupt_vector : std_logic_vector(11 downto 0) := X"3FF";
scratch_pad_memory_size : integer := 64);
port ( address : out std_logic_vector(11 downto 0);
instruction : in std_logic_vector(17 downto 0);
bram_enable : out std_logic;
in_port : in std_logic_vector(7 downto 0);
out_port : out std_logic_vector(7 downto 0);
port_id : out std_logic_vector(7 downto 0);
write_strobe : out std_logic;
k_write_strobe : out std_logic;
read_strobe : out std_logic;
interrupt : in std_logic;
interrupt_ack : out std_logic;
sleep : in std_logic;
reset : in std_logic;
clk : in std_logic);
end component;
Déclaration de la mémoire
component prog
generic( C_FAMILY : string := "S6";
C_RAM_SIZE_KWORDS : integer := 1;
C_JTAG_LOADER_ENABLE : integer := 0);
Port ( address : in std_logic_vector(11 downto 0);
instruction : out std_logic_vector(17 downto 0);
enable : in std_logic;
rdl : out std_logic;
clk : in std_logic);
end component;
Déclaration des signaux
signal instr_adr : std_logic_vector(11 downto 0);
signal inst : std_logic_vector(17 downto 0);
signal bram_enable : std_logic;
signal in_port : std_logic_vector(7 downto 0);
signal out_port : std_logic_vector(7 downto 0);
signal port_id : std_logic_vector(7 downto 0);
signal wr_en : std_logic;
signal k_write_strobe : std_logic;
signal read_strobe : std_logic;
signal interrupt : std_logic;
signal interrupt_ack : std_logic;
signal kcpsm6_sleep : std_logic;
signal kcpsm6_reset : std_logic;
signal cpu_reset : std_logic;
signal rdl : std_logic;
signal int_request : std_logic;
Instanciation du up
processor: kcpsm6
generic map ( hwbuild => X"00",
interrupt_vector => X"3FF",
scratch_pad_memory_size => 64)
port map( address => instr_adr, instruction => inst, bram_enable => bram_enable, port_id => open,
write_strobe => wr_en,
k_write_strobe => open, out_port => out_port, read_strobe => open,
in_port => sw, interrupt => '0',
interrupt_ack => open,
sleep => '0',
reset => rdl,
clk => clk);
Instanciation de la mémoire
program_rom: prog --Name to match your PSM file
generic map( C_FAMILY => "7S", --Family 'S6', 'V6' or '7S'
C_RAM_SIZE_KWORDS => 1, --Program size '1', '2' or '4'
C_JTAG_LOADER_ENABLE => 1) --Include JTAG Loader
when set to '1'
port map( address => instr_adr,
instruction => inst,
enable => bram_enable,
rdl => rdl,
clk => clk);
le programme en assembleur
DISABLE INTERRUPT
Boucle :
INPUT S0,00
OUTPUT S0,00
jump Boucle
NB: enregistrer avec le nom [Link]
• Ajouter du up et de la mémoire au projet
• Ajouter du process de sortie
process(clk)
begin
if(clk 'event and clk='1')then
if wr_en='1' then
led<=out_port;
end if;
end if;
end process;
Interruption
permet au système de répondre rapidement aux actions de l’utilisateur
sans nécessites une surveillance constante du bouton par le programme
principal
Le picoblaze dispose d’une
entrée d’interruption
externe unique
Mécanisme d’interruption du PicoBlaze
Lorsqu’un signal de niveau haut est appliqué à l’entrée d’interruption
L’interruption est autorisée par l’instruction ENABLE INTERRUPT
le PicoBlaze interrompt l’exècution normal du programme pour
sauter à une Routine de Service d’Interruption (ISR) située à l’adresse
d’interruption généralement 0X3FF.
Exemple d’interruption: à chaque interruption, incrémenter le registre S3
processor: kcpsm6
generic map ( hwbuild => X"00",
Instanciation interrupt_vector => X"3FF",
scratch_pad_memory_size => 64)
port map( address => instr_adr,….
Enable interrupt
.
.
Code assembleur Adresse 3FF
ISR: add S3,01
Returni enable
Les instructions
•ENABLE INTERRUPT: permet d’activer la gestion des interruptions dans un programme PicoBl
•DISABLE INTERRUPT: Désactive temporairement les interruptions.
•RETURNI DISABLE : revient de l'interruption mais laisse les interruptions désactivées.
•RETURNI ENABLE : revient de l'interruption et réactive les interruptions.
Cahier de charge:
soit le système embarque défini par la figure suivante:
Le fonctionnement est décrit comme suite:
• Un timer qui donne une interruption toutes les secondes à PicoBlaze.
• La routine d’interruption : Permet d’ inverser l'état des interrupteurs
(switches) vers les LED de la carte
interruption: process (clk)
TIMER: process(clk) begin
variable cmp: integer; if(clk'event and clk='1') then
if (int_ack='1') then
interrupt<='0';
begin elsif (timer_trig='1')then
interrupt<='1';
if(clk'event and clk='1') then end if;
cmp<=cmp+1; end if;
timer_trig<='0'; end if;
end process;
if(cmp=99999999)then
cmp<=0;
timer_trig<='1';
end if;
end if;
end process;
Partie logiciel
ENABLE INTERRUPT
loop : jump loop
isr:
input s0,00
xor s0,FF
output s0,00
RETURNI ENABLE
address 3FF
jump isr