Very High Speed Integrated Circuit Hardware Description Language/Travail pratique/TP 5
Nous allons dans ce dernier chapitre mettre en œuvre des processeurs softcore variés. Je ne pense pas qu’il y ait un intérêt particulier pour un étudiant de connaître tous les processeurs softcores présentés. Faites votre choix parmi le PicoBlaze, le PIC 16F84 et le ATMega8. Nous commençons par le PicoBlaze.
Le PicoBlaze
modifierAvant de débuter ce TP, essayez d'obtenir le fichier "kcpsm3.zip" chez Xilinx. Cela vous permettra d’avoir l'assembleur (sous Windows), et surtout le fichier kcpsm3.vhd qui décrit le PicoBlaze.
Nous allons commencer par une mise en œuvre du PicoBlaze sans nous occuper de la lecture d'un clavier PS/2. Le plus simple est donc d’utiliser les interrupteurs de la carte et les afficheurs sept segments.
PicoBlaze sans clavier PS/2
modifierOn désire faire fonctionner le PicoBlaze pour réaliser l’affichage complet sur 8 bits et deux digits du TP 1.
Architecture
modifier- Entrées : 8 bits en entrées correspondent à un PORT. Il vous faut donc partir de l'architecture à quatre PORTs présentée dans le cours et la simplifier pour en garder un seulement.
- Sorties : un port est nécessaire pour gérer les sept segments, un autre pour gérer la sélection des afficheurs.
Il est temps de présenter le schéma à implanter :
Dans ce schéma le démultiplexeur est responsable d'envoyer le signal write_strobe en fonction du bit de poids faible de port_id sur une de ses deux sorties. Les bascules D sont naturellement des registres 8 bits avec entrée de validation. Quelque chose comme :
process(clk) begin
if clk'event and clk = '1' then
if en0 ='1' then
q_lsb <= s_out_port ;
end if;
end if;
end process;
devrait convenir.
Le morceau de programme donné ci-dessus est une implantation sans composant, donc directement dans un process d'où la présence de signaux (que je note souvent avec le préfixe "s_"). Si vous utilisez des composants changez les noms de variables ci-dessus. |
Le contenu de la mémoire programme à gauche de la figure vous est donné un peu plus loin dans ce document.
Programme
modifierPour simplifier le développement on vous donne le programme complet de gestion des afficheurs. Évidemment le PicoBlaze fonctionnant à 50 Mhz, il faut gérer des boucles d'attentes.
;;; Sortie sur deux digits constant MAX, FF namereg s0,i NAMEREG s1, octet_lsb NAMEREG s3, s7seg ; rename register s3 as “s7seg” NAMEREG s4, Aff debut: ; initialisation RAM : table de conversion LOAD s0,01 STORE s0,00 LOAD s0,4F STORE s0,01 LOAD s0,12 STORE s0,02 LOAD s0,06 STORE s0,03 LOAD s0,4C STORE s0,04 LOAD s0,24 STORE s0,05 LOAD s0,20 STORE s0,06 LOAD s0,0F STORE s0,07 LOAD s0,00 STORE s0,08 LOAD s0,04 STORE s0,09 LOAD s0,08 STORE s0,0A LOAD s0,60 STORE s0,0B LOAD s0,31 STORE s0,0C LOAD s0,42 STORE s0,0D LOAD s0,30 STORE s0,0E LOAD s0,38 STORE s0,0F boucle: ;entree des {{Unité|8|bits}} INPUT octet_lsb,0 AND octet_lsb,0F ;conversion par RAM FETCH s7seg,(octet_lsb) ;sortie 7 segs OUTPUT s7seg,0 LOAD Aff,FE ;sélection afficheur OUTPUT Aff,1 CALL wait ; maintenant {{Unité|4|bits}} poids forts INPUT octet_lsb,0 SR0 octet_lsb SR0 octet_lsb SR0 octet_lsb SR0 octet_lsb AND octet_lsb,0F ;inutile en principe ;conversion par RAM FETCH s7seg,(octet_lsb) ;sortie 7 segs OUTPUT s7seg,0 LOAD Aff,FD ;sélection afficheur OUTPUT Aff,1 CALL wait JUMP boucle wait: LOAD i,MAX loop: SUB i,01 JUMP NZ,loop RETURN
La boucle d'attente présentée est relativement rapide avec une horloge à 50 Mhz, mais des tests ont montré le bon fonctionnement de ce programme. Pour une autre carte il faudrait éventuellement ralentir en faisant une double boucle ou en appelant plusieurs fois de suite le sous-programme "wait". |
Un programme assembleur est ensuite assemblé pour donner un composant VHDL représentant le contenu de la ROM du PicoBlaze. Pour éviter la compilation aux étudiants dans un premier temps, je donne le contenu VHDL équivalent au programme adssembleur. Pour éviter de polluer cette page avec un long programme VHDL pas utile pour tout le monde, je met le programme correspondant dans une boîte déroulante :
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--
-- The Unisim Library is used to define Xilinx primitives. It is also used during
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
--
library unisim;
use unisim.vcomponents.all;
entity mpu_rom is
Port ( address : in std_logic_vector(9 downto 0);
instruction : out std_logic_vector(17 downto 0);
clk : in std_logic);
end mpu_rom;
--
architecture low_level_definition of mpu_rom is
attribute INIT_00 : string;
attribute INIT_01 : string;
attribute INIT_02 : string;
attribute INIT_03 : string;
attribute INIT_04 : string;
attribute INIT_05 : string;
attribute INIT_06 : string;
attribute INIT_07 : string;
attribute INIT_08 : string;
attribute INIT_09 : string;
attribute INIT_0A : string;
attribute INIT_0B : string;
attribute INIT_0C : string;
attribute INIT_0D : string;
attribute INIT_0E : string;
attribute INIT_0F : string;
attribute INIT_10 : string;
attribute INIT_11 : string;
attribute INIT_12 : string;
attribute INIT_13 : string;
attribute INIT_14 : string;
attribute INIT_15 : string;
attribute INIT_16 : string;
attribute INIT_17 : string;
attribute INIT_18 : string;
attribute INIT_19 : string;
attribute INIT_1A : string;
attribute INIT_1B : string;
attribute INIT_1C : string;
attribute INIT_1D : string;
attribute INIT_1E : string;
attribute INIT_1F : string;
attribute INIT_20 : string;
attribute INIT_21 : string;
attribute INIT_22 : string;
attribute INIT_23 : string;
attribute INIT_24 : string;
attribute INIT_25 : string;
attribute INIT_26 : string;
attribute INIT_27 : string;
attribute INIT_28 : string;
attribute INIT_29 : string;
attribute INIT_2A : string;
attribute INIT_2B : string;
attribute INIT_2C : string;
attribute INIT_2D : string;
attribute INIT_2E : string;
attribute INIT_2F : string;
attribute INIT_30 : string;
attribute INIT_31 : string;
attribute INIT_32 : string;
attribute INIT_33 : string;
attribute INIT_34 : string;
attribute INIT_35 : string;
attribute INIT_36 : string;
attribute INIT_37 : string;
attribute INIT_38 : string;
attribute INIT_39 : string;
attribute INIT_3A : string;
attribute INIT_3B : string;
attribute INIT_3C : string;
attribute INIT_3D : string;
attribute INIT_3E : string;
attribute INIT_3F : string;
attribute INITP_00 : string;
attribute INITP_01 : string;
attribute INITP_02 : string;
attribute INITP_03 : string;
attribute INITP_04 : string;
attribute INITP_05 : string;
attribute INITP_06 : string;
attribute INITP_07 : string;
attribute INIT_00 of ram_1024_x_18 : label is "E007000FE0060020E0050024E004004CE0030006E0020012E001004FE0000001";
attribute INIT_01 of ram_1024_x_18 : label is "E00F0038E00E0030E00D0042E00C0031E00B0060E00A0008E0090004E0080000";
attribute INIT_02 of ram_1024_x_18 : label is "04FDC3007310A10F010E010E010E010E41000033C40104FEC3007310A10F4100";
attribute INIT_03 of ram_1024_x_18 : label is "000000000000000000000000000000000000A0005434C001025540200033C401";
attribute INIT_04 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_05 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_06 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_07 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_08 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_09 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0A of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0B of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0C of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0D of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0E of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0F of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_10 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_11 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_12 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_13 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_14 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_15 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_16 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_17 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_18 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_19 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1A of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1B of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1C of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1D of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1E of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1F of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_20 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_21 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_22 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_23 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_24 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_25 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_26 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_27 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_28 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_29 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2A of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2B of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2C of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2D of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2E of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2F of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_30 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_31 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_32 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_33 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_34 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_35 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_36 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_37 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_38 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_39 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3A of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3B of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3C of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3D of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3E of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3F of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_00 of ram_1024_x_18 : label is "0000000000000000000000000000000000002D3E20AA38808888888888888888";
attribute INITP_01 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_02 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_03 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_04 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_05 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_06 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_07 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
--
begin
--Instantiate the Xilinx primitive for a block RAM
ram_1024_x_18: RAMB16_S18
--synthesis translate_off
--INIT values repeated to define contents for functional simulation
generic map ( INIT_00 => X"E007000FE0060020E0050024E004004CE0030006E0020012E001004FE0000001",
INIT_01 => X"E00F0038E00E0030E00D0042E00C0031E00B0060E00A0008E0090004E0080000",
INIT_02 => X"04FDC3007310A10F010E010E010E010E41000033C40104FEC3007310A10F4100",
INIT_03 => X"000000000000000000000000000000000000A0005434C001025540200033C401",
INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_00 => X"0000000000000000000000000000000000002D3E20AA38808888888888888888",
INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
--synthesis translate_on
port map( DI => "0000000000000000",
DIP => "00",
EN => '1',
WE => '0',
SSR => '0',
CLK => clk,
ADDR => address,
DO => instruction(15 downto 0),
DOP => instruction(17 downto 16));
end low_level_definition;
Exercice
modifierOn vous demande de réaliser l'architecture globale utilisant le PicoBlaze, la mémoire les PORTs de sortie. En ce qui concerne le PORT d'entrée on se contentera de faire ce qu'on ne fait jamais, de relier directement les entrées au PORT d'entrée du PicoBlaze.
Comme indiqué dans l'exercice il est fortement déconseillé de relier des entrées asynchrones directement sur une architecture synchrone. Normalement il faut rajouter un registre en entrée. Dans le cadre de cette formation, on ne respectera pas cette règle pour cet exercice puisqu'on n'a pas l'intention de commercialiser ce montage.
PicoBlaze et clavier
modifierNous allons maintenant interfacer le clavier du TP 3 à notre PicoBlaze. Nous allons nous intéresser à la version dans laquelle on a ajouté un registre d'affichage. Ce registre d'affichage constituera un port d'entrées. Un autre port d'entrée sera encore constitué par les interrupteurs. Ces interrupteurs doivent servir à naviguer dans la mémoire donnée du picoblaze. Le fonctionnement est donc le suivant :
- Pour chaque appui de touches sur le clavier une interruption est générée qui vient lire l'octet qui vient d’être lu pour le ranger en mémoire (après l'adresse 0x00F).
- La session d'acquisition étant terminée, il vous est possible de naviguer dans la mémoire donnée pour afficher les scancodes reçus : la navigation se fait en binaire avec les quatre interrupteurs.
Notre programme
modifierLe programme est naturellement plus complexe que le précédent puisqu’il gère une interruption.
;;; Sortie sur deux digits constant MAX, 80 namereg s0,i NAMEREG s1, octet_lsb NAMEREG s2, adr_mem NAMEREG s3, s7seg ; rename register s3 as “s7seg” NAMEREG s4, Aff NAMEREG s5, switch NAMEREG s6, ps2 debut: ENABLE Interrupt ; initialisation RAM : table de conversion LOAD s0,01 STORE s0,00 LOAD s0,4F STORE s0,01 LOAD s0,12 STORE s0,02 LOAD s0,06 STORE s0,03 LOAD s0,4C STORE s0,04 LOAD s0,24 STORE s0,05 LOAD s0,20 STORE s0,06 LOAD s0,0F STORE s0,07 LOAD s0,00 STORE s0,08 LOAD s0,04 STORE s0,09 LOAD s0,08 STORE s0,0A LOAD s0,60 STORE s0,0B LOAD s0,31 STORE s0,0C LOAD s0,42 STORE s0,0D LOAD s0,30 STORE s0,0E LOAD s0,38 STORE s0,0F ;initialisation pointeur mémoire LOAD adr_mem,10 boucle: ;lecture des switchs INPUT switch,1 ;; AND switch,0F ;; ADD switch,10 ;entree des {{Unité|8|bits}} FETCH octet_lsb,(switch) ;je ne garde que la partie basse : AND octet_lsb,0F ;conversion par RAM FETCH s7seg,(octet_lsb) ;sortie 7 segs OUTPUT s7seg,0 LOAD Aff,FE ;sélection afficheur droite OUTPUT Aff,1 CALL wait ; maintenant {{Unité|4|bits}} poids forts INPUT switch,1 ;; AND switch,0F ;; ADD switch,10 ;entree des {{Unité|8|bits}} FETCH octet_lsb,(switch) ;decalage de {{Unité|4|bits}} vers la droite SR0 octet_lsb SR0 octet_lsb SR0 octet_lsb SR0 octet_lsb ;conversion par RAM FETCH s7seg,(octet_lsb) ;sortie 7 segs OUTPUT s7seg,0 LOAD Aff,FD ;sélection afficheur gauche OUTPUT Aff,1 CALL wait ;;;;;;; to remove INPUT ps2,0 ;; LOAD ps2,1F ;; ADD ps2,01 STORE ps2,(adr_mem) ;; ADD adr_mem,01 ;;;;;;;;;end to remove JUMP boucle ;=== boucle d'attente=== wait: LOAD i,MAX loop: SUB i,01 JUMP NZ,loop RETURN ;=== code de l'interuption=== isr: ; lecture du registre PS2 ;; INPUT ps2,0 LOAD ps2,20 ADD ps2,adr_mem ; stockage en RAM STORE ps2,(adr_mem) ;increment adresse RAM ADD adr_mem,01 RETURNI ENABLE ;=== verteur d'interruption=== ADDRESS 0X3FF JUMP isr
Exercice
modifierRéaliser l'architecture complète.
Le PIC 16F84 embarqué
modifierL'ensemble de ce chapitre n'a pas encore été testé. Ainsi le programme C donné ne comporte aucune erreur de syntaxe puisqu’il a été compilé mais peut comporter des erreurs sémantiques !!! |
Un moyen de commencer avec un projet simple est d’utiliser le PIC 16F84 pour afficher sur deux afficheurs sept segments multiplexés. L'intérêt par rapport au PicoBlaze est que maintenant on peut travailler avec le langage C.
Le PIC16F84 pour gérer des afficheurs sept segments
modifierNotre objectif est assez modeste : afficher une donnée provenant de huit interrupteurs sur deux afficheurs sept segments en hexadécimal. Nous commençons par donner notre programme en C.
Le programme de départ en C
modifierNous avons choisi PORTA pour gérer les afficheurs et PORTB en entrée pour les interrupteurs et PORTB en sortie pour les afficheurs sept segments.
#include <pic.h>
char conv[]={0x01,0x4F,0x12,0x06,0x4C,0x24,0x20,0x0F,0x00,0x04,
0x08,0x60,0x31,0x42,0x30,0x38};
void wait(unsigned char tempo);
void main(void)
{ char entree_PORTB,pdsfaible,pdsfort;
TRISA = 0x00; // PORTA en sortie
while(1) {
// Lecture du port B
TRISB = 0xFF;
entree_PORTB=PORTB;
// calcul intermédiaire
pdsfaible = entree_PORTB & 0x0F;
pdsfort = (entree_PORTB >> 4) & 0x0F;
// sortie du port B
TRISB = 0x00;
PORTB=conv[pdsfaible];
// sélection afficheur poids faible
PORTA = 0xFE;
wait(255); // On attend
PORTB=conv[pdsfort];
// sélection afficheur poids faible
PORTA = 0xFD;
wait(255); // On attend
}
}
void wait(unsigned char tempo){
OPTION=0x07; // div 256 et source=quartz
TMR0 =0;
while(TMR0<tempo);
}
Les habitués aux processeurs physiques ne percevront pas de suite comment un même PORT (le PORTB) peut être utilisé à la fois en entrée et en sortie. Il me faut donc rappeler que notre cœur possède physiquement deux ports séparés, un pour les entrées et l'autre pour les sorties.
On rappelle qu'une fois le programme C compilé, on dispose d'un fichier .hex qui doit être transformer en VHDL avec l'utilitaire approprié.
Le fichier mémoire ROM
modifierSi le fichier à convertir s’appelle demo16F84.hex on utilise la commande :
hex2rom demo16F84.hex progrom 13l14s >progrom.vhd
Le fichier progrom.vhd possède plus de 1000 lignes et il nous est donc impossible de le donner pour éviter aux utilisateurs la compilation. On va vous donner le fichier .hex, beaucoup plus compact :
- 10001000840A0408503A03191528FF0A0319FE0A36
- 1000200006287E088A007F0882001628031083169F
- 1000300000300318013085008316FF3086008312DC
- 100040000608D20052080F39D0005208D3000430FD
- 100050000310D30CFF3E031D282853080F39D1008D
- 1000600003108316003003180130860083125008F5
- 10007000403E8313840000088600FE308500FF3078
- 10008000DE2383125108403E83138400000886005B
- 0C009000FD308500FF30DE231C28002816
- 1007BC00D400073083168100031083120030031815
- 1007CC0001308100E92B54080102031CEE2BEF2BA6
- 1007DC00E92B080001344F34123406344C342434E1
- 1007EC0020340F340034043408346034313442344F
- 0407FC003034383429
- 00000001FF
Le fichier RAM
modifierCe fichier a déjà été donné dans le chapitre Embarquer un PIC 16F84.
Le projet complet
modifierÀ faire