[Armadeus-commitlog] SF.net SVN: armadeus: [760] trunk/firmware
Brought to you by:
sszy
|
From: <th...@us...> - 2008-02-10 14:33:25
|
Revision: 760
http://armadeus.svn.sourceforge.net/armadeus/?rev=760&view=rev
Author: thom25
Date: 2008-02-10 06:33:27 -0800 (Sun, 10 Feb 2008)
Log Message:
-----------
add servo controler from Yvan Roch
Added Paths:
-----------
trunk/firmware/servo/
trunk/firmware/servo/CLK_GENERATOR.vhd
trunk/firmware/servo/README.txt
trunk/firmware/servo/SERVO_top.vhd
trunk/firmware/servo/pwm_module.vhd
trunk/firmware/servo/servo.ucf
Added: trunk/firmware/servo/CLK_GENERATOR.vhd
===================================================================
--- trunk/firmware/servo/CLK_GENERATOR.vhd (rev 0)
+++ trunk/firmware/servo/CLK_GENERATOR.vhd 2008-02-10 14:33:27 UTC (rev 760)
@@ -0,0 +1,84 @@
+----------------------------------------------------------------------------------
+-- Company: Armadeus Project
+-- Engineer: Yvan Roch
+--
+-- Create Date: 2007-12-03
+-- Design Name:
+-- Module Name: CLK_GENERATOR - behavioral
+-- Project Name:
+-- Target Devices: Spartan3 Armadeus
+-- Tool versions: ISE 9.2.02i
+-- Description: Servo Contoller
+--
+-- Dependencies:
+--
+-- Revision:
+-- Revision 0.01 - File Created
+-- Additional Comments:
+-- Ce module est un diviseur d'horloge, il fourni un signal d'horloge a 4MHz
+-- et maintient le compteur 16 bits utilise par tous les modules PWM
+----------------------------------------------------------------------------------
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+entity CLK_GENERATOR is
+ port (clkIn : in STD_LOGIC; -- Entree de l'horloge a 96 MHz provenant du MC9328MXL
+ counterOut16Bits : out std_logic_vector(15 downto 0); -- Compteur 16 bits utilise par tous les modules PWM
+ writeValue : out STD_LOGIC); -- Validation de la mise a jour des registres internes des modules PWM
+end entity CLK_GENERATOR;
+
+architecture behavioral of CLK_GENERATOR is
+ signal clkInternalOut : STD_LOGIC := '0'; -- Registre interne du generateur 4MHz
+ signal counter : std_logic_vector(15 downto 0) := X"0000"; -- Registre interne du compteur
+
+begin
+ -- generation du signal 4MHz
+ process (clkIn)
+ variable countMax : integer; -- Valeur numerique du countMax
+ variable count : integer;
+
+ begin
+ -- Sur front montant de clkIn
+ if (clkIn'event) and (clkIn = '1') then
+ -- Compte le nombre de cycle d'horloge
+ count := count + 1;
+ -- Pour une frequence de sortie de 4MHz
+ countMax := 24;
+ -- Si countMax/2 est atteint
+ -- La frequence de sortie vaut: 1/((1/96000000)*countMax)
+ if (count = countMax/2) then
+ clkInternalOut <= not clkInternalOut;
+ count := 0;
+ end if;
+ end if;
+ end process;
+
+ -- gestion du compteur 16 bits
+ process (clkInternalOut)
+
+ begin
+ -- Sur front montant de clkInternalOut
+ if (clkInternalOut'event and clkInternalOut = '1') then
+ counter <= counter + 1;
+ -- Sortie de la valeur du compteur
+ counterOut16Bits <= counter;
+ -- Generation du signal writeValue
+ if (counter > "1111100000110000") then
+ -- Debut de la generation de l'impulsion PWM (partie constante de 0.5ms)
+ -- a la valeur 63536 du counter
+ -- => Mise a jour des registres interdite
+ writeValue <= '0';
+ elsif (counter < "0001111111111110") then
+ -- Generation impulsions PWM en cours
+ -- valeur maximale du compteur 12 bits
+ -- => Mise a jour des registres interdite
+ writeValue <= '0';
+ else
+ -- Dans les autre cas, les sorties PWM sont a 0 => Mise jour des registres possible
+ writeValue <= '1';
+ end if;
+ end if;
+ end process;
+end architecture behavioral;
Added: trunk/firmware/servo/README.txt
===================================================================
--- trunk/firmware/servo/README.txt (rev 0)
+++ trunk/firmware/servo/README.txt 2008-02-10 14:33:27 UTC (rev 760)
@@ -0,0 +1,166 @@
+Ce projet est un firmware FPGA de contolleur de servo de telecommande.
+Une description de ce genre de servos peut \xEAtre trouve a:
+http://fribotte.free.fr/bdtech/pic/pic_et_servo.html
+Il est inspire du projet "Atmel AVR 2004 Design Contest Entry Project Number A3722"
+de Circuit Cellar par Eric Gagnon :
+http://www.circuitcellar.com/avr2004/HA3722.html
+Ce controleur de servo permet de controler jusqu'a 24 servos.
+Il est facilement extensible a plus.
+
+L'utilisation d'un FPGA est justifie car avec les sorties classiques d'un microcontroleur,
+meme avec l'utilisation d'un timer hardware et d'une programmation en assembleur,
+le repect precis des largeurs des impulsions PWM est quasi impossible surtout avec
+un nombre eleve de servos a commander.
+Un FPGA permet de realiser une concurence vraie dans la generation des signaux.
+D'ailleurs avec ce controleur, il n'y a pas de fretillement des servos quelque
+soient leur position les uns par rapport aux autres, ce qui n'est pas le cas
+dans une solution classique a microcontoleur.
+
+1 - CREATION D'UN NOUVEAU PROJET DANS XILINX ISE
+Version Xilinx ISE 9.2.04i
+Creer le nouveau projet:
+File->New Project
+Selectionner Top Level Source: HDL (Harware Description Language)
+Pour le FPGA de la carte Armadeus choisir:
+Family: Spartan3
+Device: XC3S200
+Package: TQ144
+Speed: -4
+Top Level Source: HDL
+Synthesis Tool: XST
+Simulator: ISE Simulator (VHDL/Verilog)
+Preferred Language: VHDL
+
+Importer les fichiers sources dans le projet ISE:
+Projet->Add Source
+Selectionner les fichiers:
+SERVO_top.vhd
+CLK_GENERATOR.vhd
+pwm_module.vhd
+servo.ucf
+
+2 - SYNTHESE - CREATION DU FICHIER FIRMWARE SERVO_top.bit
+Generate Programming File->clic droit->Run
+
+3 - CHARGEMENT DU FIRMWARE SERVO_top.bit DANS L'APF9328
+Se placer dans le repertoire qui contient le fichier SERVO_top.bit
+
+Etablir une connexion RS232 avec l'APF9328 comme le decrit:
+http://www.armadeus.com/wiki/index.php?title=Connection_with_U-Boot_on_Linux
+
+Mettre sous tension l'APF9328
+Au message Hit any key to stop autoboot:
+Appuyer sur une touche pour obtenir le prompt:
+BIOS>
+
+Choisir l'emplacement memoire de l'upload:
+loadb 08000000
+
+Le message:
+## Ready for binary (kermit) download to 0x08000000 at 115200 bps...
+apparait.
+
+Passer en mode commande Kermit:
+Ctrl+Altgr+\+c
+
+Upload du fichier:
+send SERVO_top.bit
+
+Kermit upload le fichier.
+Taper c pour reconnecter le terminal.
+
+Flasher le firmware:
+run flash_firmware
+
+Charger le firmware dans le FPGA:
+fpga load 0 ${firmware_addr} ${firmware_len}
+
+Pour un chargement automatique au boot:
+setenv firmware_autoload 1
+saveenv
+
+Le firmware est maintenant charge et utilisable.
+
+4 - UTILISATION DU FIRMWARE
+Actuellement seul le firmware est ecrit.
+Les servos sont a brancher sur les ports de la DevLight suivants via un buffer
+74HCT244:
+L24N_3/P87 -> servo 00
+L24P_3/P86 -> servo 01
+L23N_3/P85 -> servo 02
+L40P_2/P92 -> servo 03
+L40N_3/P90 -> servo 04
+L40P_3/P89 -> servo 05
+L24N_2/P96 -> servo 06
+L24P_2/P95 -> servo 07
+L40N_2/P93 -> servo 08
+L22P_2/P99 -> servo 09
+L23N_2/P98 -> servo 10
+L23P_2/P97 -> servo 11
+L21N_2/P103 -> servo 12
+L21P_2/P102 -> servo 13
+L22N_2/P100 -> servo 14
+L01P_2/P107 -> servo 15
+L20N_2/P105 -> servo 16
+L20P_2/P104 -> servo 17
+L32N_0/P128 -> servo 18
+L32P_0/P127 -> servo 19
+L01N_2/P108 -> servo 20
+L31P_0/P129 -> servo 21
+L31N_0/P130 -> servo 22
+L32N_1/P125 -> servo 23
+
+Commande BIOS pour le controle des servos:
+Au chargement du firmware, tous les servos sont desactives.
+
+Activation des servos 0-15:
+mw.w 12000040 FFFF
+
+Activation des servos 16-23:
+mw.w 12000042 00FF
+
+Desactivation des servos 0-15:
+mw.w 12000040 0000
+
+Desactivation des servos 16-23:
+mw.w 12000042 0000
+
+Au chargement du firmware, tous les servos sont en position mediane.
+Positionnement du servo 0 a la position maximale anti-horaire:
+mw.w 12000000 0000
+Positionnement du servo 0 a la position maximale horaire:
+mw.w 12000000 0FFF
+Positionnement du servo 0 a la position mediane:
+mw.w 12000000 0800
+
+Voici les adresses a utiliser pour les autres servos:
+0x12000000 -> servo 0
+0x12000002 -> servo 1
+0x12000004 -> servo 2
+0x12000006 -> servo 3
+0x12000008 -> servo 4
+0x1200000A -> servo 5
+0x1200000C -> servo 6
+0x1200000E -> servo 7
+0x12000010 -> servo 8
+0x12000012 -> servo 9
+0x12000014 -> servo 10
+0x12000016 -> servo 11
+0x12000018 -> servo 12
+0x1200001A -> servo 13
+0x1200001C -> servo 14
+0x1200001E -> servo 15
+0x12000020 -> servo 16
+0x12000022 -> servo 17
+0x12000024 -> servo 18
+0x12000026 -> servo 19
+0x12000028 -> servo 20
+0x1200002A -> servo 21
+0x1200002C -> servo 22
+0x1200002E -> servo 23
+
+5 - ROAD MAP
+De futurs developpements sont en cours:
+ - Driver Linux pour le firmware FPGA,
+ - Daemon de commande des servos via le driver Linux,
+ - Client reseau pour daemon de commande...
Added: trunk/firmware/servo/SERVO_top.vhd
===================================================================
--- trunk/firmware/servo/SERVO_top.vhd (rev 0)
+++ trunk/firmware/servo/SERVO_top.vhd 2008-02-10 14:33:27 UTC (rev 760)
@@ -0,0 +1,608 @@
+----------------------------------------------------------------------------------
+-- Company: Armadeus Project
+-- Engineer: Yvan ROCH
+--
+-- Create Date: 2007-12-03
+-- Design Name:
+-- Module Name: SERVO_top - structural
+-- Project Name: SERVO
+-- Target Devices: Spartan3 Armadeus
+-- Tool versions: ISE 9.2.02i
+-- Description: Servo Contoller
+--
+-- Dependencies:
+--
+-- Revision:
+-- Revision 0.01 - File Created
+-- Additional Comments:
+-- Ce projet est un firmware FPGA de contolleur de servo de telecommande
+-- Il est inspirer du projet "Atmel AVR 2004 Design Contest Entry Project Number A3722"
+-- de Circuit Cellar par Eric Gagnon :
+-- http://www.circuitcellar.com/avr2004/HA3722.html
+--
+-- Ce controleur de servo permet de controle jusqu'a 24 servos.
+-- Il est facilement extensible a plus.
+--
+-- Chaque registre de servo (0x12000000 - 0x1200002E) est un registre 16 bits
+-- avec 12 bits significatifs contenant la position du servo concerne.
+-- 0000 ecrit a l'adresse 0x12000000 positionnera le servo 0 a la position maximale anti-horaire
+-- 0800 ecrit a l'adresse 0x12000000 positionnera le servo 0 a la position mediane
+-- 0FFF ecrit a l'adresse 0x12000000 positionnera le servo 0 a la position maximale horaire
+-- Les registres 0x12000030 et 0x12000032 sont les registres de validation des servos
+-- 0001 ecrit a l'adresse 0x12000030 activera le servo 0
+-- 0001 ecrit a l'adresse 0x12000032 activera le servo 16
+--
+-- Decodage d'adresse:
+-- 0x12000000 servo 0
+-- 0x12000002 servo 1
+-- 0x12000004 servo 2
+-- 0x12000006 servo 3
+-- 0x12000008 servo 4
+-- 0x1200000A servo 5
+-- 0x1200000C servo 6
+-- 0x1200000E servo 7
+-- 0x12000010 servo 8
+-- 0x12000012 servo 9
+-- 0x12000014 servo 10
+-- 0x12000016 servo 11
+-- 0x12000018 servo 12
+-- 0x1200001A servo 13
+-- 0x1200001C servo 14
+-- 0x1200001E servo 15
+-- 0x12000020 servo 16
+-- 0x12000022 servo 17
+-- 0x12000024 servo 18
+-- 0x12000026 servo 19
+-- 0x12000028 servo 20
+-- 0x1200002A servo 21
+-- 0x1200002C servo 22
+-- 0x1200002E servo 23
+-- 0x12000030 Registre de validation LSB
+-- 0x12000032 Registre de validation MSB
+
+--
+----------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+entity SERVO_top is
+ port ( -- MC9328MXL pins
+ -- Bus de donnees 16 bits
+ DataxD : inout std_logic_vector(15 downto 0);
+
+ -- Bus d'adresses A0-A12
+ -- L'adresse de base du Spartan3 est 0x12000000
+ AddrxDI : in std_logic_vector(12 downto 0);
+
+ -- Acces en ecriture (APF9328: CTRL9, Spartan3 pin 60, MC9328MXL: EB3n pin M5) Actif Bas
+ -- Ce signal du MC9328MXL est actif au niveau bas en ecriture ET en lecture
+ -- Selon le Data Sheet du MC9328MXL P4:
+ -- LSB Byte Strobe?Active low external enable byte signal that controls D [7:0].
+ -- Voir timing Write P28
+ WRxBI : in std_logic;
+
+ -- Acces en lecture (APF9328: CTRL10, Spartan3 pin 63, MC9328MXL: OEn pin R5) Actif Bas
+ -- Ce signal du MC9328MXL est actif au niveau bas en lecture UNIQUEMENT
+ -- Selon le Data Sheet du MC9328MXL P4:
+ -- Memory Output Enable?Active low output enables external data bus.
+ -- Voir timing Read P26
+ RDxBI : in std_logic;
+
+ -- Remarque sur WRxBI et RDxBI:
+ -- RDxBI est en fait OEn, actif lors de la lecture UNIQUEMENT sur le bus externe du MC9328MXL
+ -- WRxBI est en fait EB3n, actif lors de l'acc\xE8s a l'octet de poids faible du bus de donn\xE9es en lecture ET en ecriture
+ -- Ce n'est pas tr\xE8s clair car ces deux signaux ne sont pas mutuellement exclusifs!!!
+ -- En resum\xE9:
+ -- Lors d'une lecture: RDxBI=0 et WRxBI=0 (les 2 actifs a 0)
+ -- Lors d'une ecriture: RDxBI=1 et WRxBI=0 (les 2 actifs a 0)
+
+ -- Chip select (APF9328: CTRL1, Spartan3 pin 59, MC9328MXL: CS1n M8) Actif Bas
+ CSxBI : in std_logic;
+
+ -- Entree de l'horloge a 96 MHz provenant du MC9328MXL sur la broche P55 du Spartan3
+ clkInImx96MHz : in STD_LOGIC;
+
+ -- Declaration des 24 registres de 1 bit contenant la sortie PWM
+ pwmOut : out std_logic_vector(23 downto 0));
+
+end entity SERVO_top;
+
+architecture structural of SERVO_top is
+ -- Declaration du type reg12Array24 qui contient 24 signaux de 12 bits
+ -- Ce type est utilise pour les 24 registres de position des servos
+ type reg12Array24 is array(0 to 23) of std_logic_vector(11 downto 0);
+
+ -- Declaration des 24 registres de 16 bits contenant la position des servos
+ -- Initialisation en position mediane des servos
+ -- Position Min: 0
+ -- Position Max: FFF
+ signal servosReg : reg12Array24 := (X"800",X"800",X"800",X"800",X"800",X"800",
+ X"800",X"800",X"800",X"800",X"800",X"800",X"800",X"800",X"800",X"800",X"800",
+ X"800",X"800",X"800",X"800",X"800",X"800",X"800");
+ -- Declaration des 24 registres de 1 bit contenant la validation des servos
+ -- Initailisation: tous les servo sont desactives
+ signal enableReg : std_logic_vector(31 downto 0) := X"00000000";
+
+ -- Declaration du diviseur d'horloge
+ component CLK_GENERATOR
+ -- Declaration des ports utilises
+ port (clkIn : in STD_LOGIC;
+ counterOut16Bits : out std_logic_vector(15 downto 0);
+ writeValue : out STD_LOGIC);
+ end component CLK_GENERATOR;
+
+ -- Declaration du generateur PWM
+ component PWM_MODULE
+ -- Declaration des ports utilises
+ Port (count : in std_logic_vector(15 downto 0);
+ servosReg : in std_logic_vector( 11 downto 0);
+ enableReg: in std_logic;
+ pwmOut : out std_logic;
+ writeValue : in std_logic);
+ end component PWM_MODULE;
+
+ -- Declaration des signaux
+ -- Reset asynchrone actif bas
+ signal resetn : std_logic;
+ -- Signal de synchro de lecture
+ signal readAccessPulse : std_logic;
+ -- Signal buffer pour compteur principal
+ signal count : std_logic_vector(15 downto 0);
+ -- Signal en provenance de compteur principal signifiant que les valeurs
+ -- servosReg(X) et enableReg(X) peuvent mis a jour sans perturber la generation
+ -- de la partie utile de l'impulsion
+ signal writeValue : std_logic;
+
+ -- Definition de l'architecture
+ begin
+ -- Instantiation du generateur d'horloge
+ clockGen : CLK_GENERATOR
+ -- Mapping des ports du generateur d'horloge
+ port map (clkIn => clkInImx96MHz,
+ counterOut16Bits => count,
+ writeValue => writeValue);
+-- testOut => testOut);
+ -- Instantiation des 24 modules PWM
+ PWM0 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(0),
+ enableReg => enableReg(0),
+ pwmOut => pwmOut(0),
+ writeValue => writeValue);
+ PWM1 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(1),
+ enableReg => enableReg(1),
+ pwmOut => pwmOut(1),
+ writeValue => writeValue);
+ PWM2 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(2),
+ enableReg => enableReg(2),
+ pwmOut => pwmOut(2),
+ writeValue => writeValue);
+ PWM3 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(3),
+ enableReg => enableReg(3),
+ pwmOut => pwmOut(3),
+ writeValue => writeValue);
+ PWM4 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(4),
+ enableReg => enableReg(4),
+ pwmOut => pwmOut(4),
+ writeValue => writeValue);
+ PWM5 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(5),
+ enableReg => enableReg(5),
+ pwmOut => pwmOut(5),
+ writeValue => writeValue);
+ PWM6 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(6),
+ enableReg => enableReg(6),
+ pwmOut => pwmOut(6),
+ writeValue => writeValue);
+ PWM7 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(7),
+ enableReg => enableReg(7),
+ pwmOut => pwmOut(7),
+ writeValue => writeValue);
+ PWM8 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(8),
+ enableReg => enableReg(8),
+ pwmOut => pwmOut(8),
+ writeValue => writeValue);
+ PWM9 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(9),
+ enableReg => enableReg(9),
+ pwmOut => pwmOut(9),
+ writeValue => writeValue);
+ PWM10 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(10),
+ enableReg => enableReg(10),
+ pwmOut => pwmOut(10),
+ writeValue => writeValue);
+ PWM11 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(11),
+ enableReg => enableReg(11),
+ pwmOut => pwmOut(11),
+ writeValue => writeValue);
+ PWM12 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(12),
+ enableReg => enableReg(12),
+ pwmOut => pwmOut(12),
+ writeValue => writeValue);
+ PWM13 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(13),
+ enableReg => enableReg(13),
+ pwmOut => pwmOut(13),
+ writeValue => writeValue);
+ PWM14 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(14),
+ enableReg => enableReg(14),
+ pwmOut => pwmOut(14),
+ writeValue => writeValue);
+ PWM15 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(15),
+ enableReg => enableReg(15),
+ pwmOut => pwmOut(15),
+ writeValue => writeValue);
+ PWM16 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(16),
+ enableReg => enableReg(16),
+ pwmOut => pwmOut(16),
+ writeValue => writeValue);
+ PWM17 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(17),
+ enableReg => enableReg(17),
+ pwmOut => pwmOut(17),
+ writeValue => writeValue);
+ PWM18 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(18),
+ enableReg => enableReg(18),
+ pwmOut => pwmOut(18),
+ writeValue => writeValue);
+ PWM19 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(19),
+ enableReg => enableReg(19),
+ pwmOut => pwmOut(19),
+ writeValue => writeValue);
+ PWM20 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(20),
+ enableReg => enableReg(20),
+ pwmOut => pwmOut(20),
+ writeValue => writeValue);
+ PWM21 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(21),
+ enableReg => enableReg(21),
+ pwmOut => pwmOut(21),
+ writeValue => writeValue);
+ PWM22 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(22),
+ enableReg => enableReg(22),
+ pwmOut => pwmOut(22),
+ writeValue => writeValue);
+ PWM23 : PWM_MODULE
+ -- Mapping des ports du module PWM
+ port map (count => count,
+ servosReg => servosReg(23),
+ enableReg => enableReg(23),
+ pwmOut => pwmOut(23),
+ writeValue => writeValue);
+
+ -- Initialisation
+ resetn <= '1';
+
+ -- Processus d'ecriture dans le registre depuis le bus \xB5P
+ registerWrite: process (clkInImx96MHz, resetn)
+ begin -- process registerWrite
+ -- Reset asynchrone actif au niveau bas
+ if resetn = '0' then
+ -- Action eventuelle du Reset
+ -- Sur le front montant de clk_in_Imx_96MHz
+ elsif clkInImx96MHz'event and clkInImx96MHz = '1' then
+ if CSxBI = '0' and WRxBI = '0' then
+ -- Decodage d'adresse, adresse de base: 0x12000000
+ case AddrxDI is
+ -- 0x12000000 servo 0
+ when "0000000000000" =>
+ -- Sauvegarde dans le registre du servo 0
+ servosReg(0) <= DataxD(11 downto 0);
+ -- 0x12000002 servo 1
+ when "0000000000010" =>
+ -- Sauvegarde dans le registre du servo 1
+ servosReg(1) <= DataxD(11 downto 0);
+ -- 0x12000004 servo 2
+ when "0000000000100" =>
+ -- Sauvegarde dans le registre du servo 2
+ servosReg(2) <= DataxD(11 downto 0);
+ -- 0x12000006 servo 3
+ when "0000000000110" =>
+ -- Sauvegarde dans le registre du servo 3
+ servosReg(3) <= DataxD(11 downto 0);
+ -- 0x12000008 servo 4
+ when "0000000001000" =>
+ -- Sauvegarde dans le registre du servo 4
+ servosReg(4) <= DataxD(11 downto 0);
+ -- 0x1200000A servo 5
+ when "0000000001010" =>
+ -- Sauvegarde dans le registre du servo 5
+ servosReg(5) <= DataxD(11 downto 0);
+ -- 0x1200000C servo 6
+ when "0000000001100" =>
+ -- Sauvegarde dans le registre du servo 6
+ servosReg(6) <= DataxD(11 downto 0);
+ -- 0x1200000E servo 7
+ when "0000000001110" =>
+ -- Sauvegarde dans le registre du servo 7
+ servosReg(7) <= DataxD(11 downto 0);
+ -- 0x12000010 servo 8
+ when "0000000010000" =>
+ -- Sauvegarde dans le registre du servo 8
+ servosReg(8) <= DataxD(11 downto 0);
+ -- 0x12000012 servo 9
+ when "0000000010010" =>
+ -- Sauvegarde dans le registre du servo 9
+ servosReg(9) <= DataxD(11 downto 0);
+ -- 0x12000014 servo 10
+ when "0000000010100" =>
+ -- Sauvegarde dans le registre du servo 10
+ servosReg(10) <= DataxD(11 downto 0);
+ -- 0x12000016 servo 11
+ when "0000000010110" =>
+ -- Sauvegarde dans le registre du servo 11
+ servosReg(11) <= DataxD(11 downto 0);
+ -- 0x12000018 servo 12
+ when "0000000011000" =>
+ -- Sauvegarde dans le registre du servo 12
+ servosReg(12) <= DataxD(11 downto 0);
+ -- 0x1200001A servo 13
+ when "0000000011010" =>
+ -- Sauvegarde dans le registre du servo 13
+ servosReg(13) <= DataxD(11 downto 0);
+ -- 0x1200001C servo 14
+ when "0000000011100" =>
+ -- Sauvegarde dans le registre du servo 14
+ servosReg(14) <= DataxD(11 downto 0);
+ -- 0x1200001E servo 15
+ when "0000000011110" =>
+ -- Sauvegarde dans le registre du servo 15
+ servosReg(15) <= DataxD(11 downto 0);
+ -- 0x12000020 servo 16
+ when "0000000100000" =>
+ -- Sauvegarde dans le registre du servo 16
+ servosReg(16) <= DataxD(11 downto 0);
+ -- 0x12000022 servo 17
+ when "0000000100010" =>
+ -- Sauvegarde dans le registre du servo 17
+ servosReg(17) <= DataxD(11 downto 0);
+ -- 0x12000024 servo 18
+ when "0000000100100" =>
+ -- Sauvegarde dans le registre du servo 18
+ servosReg(18) <= DataxD(11 downto 0);
+ -- 0x12000026 servo 19
+ when "0000000100110" =>
+ -- Sauvegarde dans le registre du servo 19
+ servosReg(19) <= DataxD(11 downto 0);
+ -- 0x12000028 servo 20
+ when "0000000101000" =>
+ -- Sauvegarde dans le registre du servo 20
+ servosReg(20) <= DataxD(11 downto 0);
+ -- 0x1200002A servo 21
+ when "0000000101010" =>
+ -- Sauvegarde dans le registre du servo 21
+ servosReg(21) <= DataxD(11 downto 0);
+ -- 0x1200002C servo 22
+ when "0000000101100" =>
+ -- Sauvegarde dans le registre du servo 22
+ servosReg(22) <= DataxD(11 downto 0);
+ -- 0x1200002E servo 23
+ when "0000000101110" =>
+ -- Sauvegarde dans le registre du servo 23
+ servosReg(23) <= DataxD(11 downto 0);
+ -- 0x12000030 Registre de validation LSB
+ when "0000000110000" =>
+ -- Sauvegarde dans le registre de validation LSB
+ enableReg(15 downto 0) <= DataxD(15 downto 0);
+ -- 0x12000032 Registre de validation MSB
+ when "0000000110010" =>
+ -- Sauvegarde dans le registre de validation LSB
+ enableReg(31 downto 16) <= DataxD(15 downto 0);
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process registerWrite;
+
+ -- Processus d'acces generique en lecture depuis le bus \xB5P
+ registerReadSyn: process (clkInImx96MHz, resetn)
+ variable ReadAccessEdgeDetect : std_logic := '0';
+ begin -- process registerReadSyn
+ -- Reset asynchrone actif au niveau bas
+ if resetn = '0' then
+ ReadAccessPulse <= '1';
+ ReadAccessEdgeDetect := '0';
+ -- Sur le front montant de clk_in_Imx_96MHz
+ elsif clkInImx96MHz'event and clkInImx96MHz = '1' then
+ -- Si initialement ReadAccessEdgeDetect=0 et acces en lecture (RDxBI=0 et CSxBI=0)
+ -- Alors ReadAccessPulse=0
+ -- Au cycle d'horloge suivant si tourjours acces en lecture (RDxBI=0 et CSxBI=0)
+ -- Alors ReadAccessPulse=1
+ -- Et vice versa
+ -- On obtient donc une transition 0->1 ou 1->0 sur ReadAccessPulse
+ -- Au maximum en 2 cycle de clk_in_Imx_96MHz
+ -- Lorsque l'acces en lecture est fini ReadAccessEdgeDetect revient a 0
+ if (ReadAccessEdgeDetect = '0' and ((not CSxBI) and (not RDxBI)) = '1') then
+ ReadAccessPulse <= '0';
+ else
+ ReadAccessPulse <= '1';
+ end if;
+ -- ReadAccessEdgeDetect = 1 si lecture (RDxBI=0 et CSxBI=0)
+ ReadAccessEdgeDetect := (not CSxBI) and (not RDxBI);
+ end if;
+ end process registerReadSyn;
+
+ -- Processus de lecture du registre depuis le bus \xB5P
+ registerRead : process (CSxBI, RDxBI, AddrxDI, ReadAccessPulse)
+ begin -- process registerRead
+ -- acces en lecture (RDxBI=0 et CSxBI=0)
+ if CSxBI = '0' and RDxBI = '0' then
+ case AddrxDI is
+ -- 0x12000000 servo 0
+ when "0000000000000" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 0
+ DataxD <= "0000" & servosReg(0)(11 downto 0);
+ -- 0x12000002 servo 1
+ when "0000000000010" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 1
+ DataxD <= "0000" & servosReg(1)(11 downto 0);
+ -- 0x12000004 servo 2
+ when "0000000000100" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 2
+ DataxD <= "0000" & servosReg(2)(11 downto 0);
+ -- 0x12000006 servo 3
+ when "0000000000110" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 3
+ DataxD <= "0000" & servosReg(3)(11 downto 0);
+ -- 0x12000008 servo 4
+ when "0000000001000" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 4
+ DataxD <= "0000" & servosReg(4)(11 downto 0);
+ -- 0x1200000A servo 5
+ when "0000000001010" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 5
+ DataxD <= "0000" & servosReg(5)(11 downto 0);
+ -- 0x1200000C servo 6
+ when "0000000001100" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 6
+ DataxD <= "0000" & servosReg(6)(11 downto 0);
+ -- 0x1200000E servo 7
+ when "0000000001110" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 7
+ DataxD <= "0000" & servosReg(7)(11 downto 0);
+ -- 0x12000010 servo 8
+ when "0000000010000" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 8
+ DataxD <= "0000" & servosReg(8)(11 downto 0);
+ -- 0x12000012 servo 9
+ when "0000000010010" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 9
+ DataxD <= "0000" & servosReg(9)(11 downto 0);
+ -- 0x12000014 servo 10
+ when "0000000010100" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 10
+ DataxD <= "0000" & servosReg(10)(11 downto 0);
+ -- 0x12000016 servo 11
+ when "0000000010110" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 11
+ DataxD <= "0000" & servosReg(11)(11 downto 0);
+ -- 0x12000018 servo 12
+ when "0000000011000" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 12
+ DataxD <= "0000" & servosReg(12)(11 downto 0);
+ -- 0x1200001A servo 13
+ when "0000000011010" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 13
+ DataxD <= "0000" & servosReg(13)(11 downto 0);
+ -- 0x1200001C servo 14
+ when "0000000011100" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 14
+ DataxD <= "0000" & servosReg(14)(11 downto 0);
+ -- 0x1200001E servo 15
+ when "0000000011110" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 15
+ DataxD <= "0000" & servosReg(15)(11 downto 0);
+ -- 0x12000020 servo 16
+ when "0000000100000" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 16
+ DataxD <= "0000" & servosReg(16)(11 downto 0);
+ -- 0x12000022 servo 17
+ when "0000000100010" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 17
+ DataxD <= "0000" & servosReg(17)(11 downto 0);
+ -- 0x12000024 servo 18
+ when "0000000100100" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 18
+ DataxD <= "0000" & servosReg(18)(11 downto 0);
+ -- 0x12000026 servo 19
+ when "0000000100110" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 19
+ DataxD <= "0000" & servosReg(19)(11 downto 0);
+ -- 0x12000028 servo 20
+ when "0000000101000" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 20
+ DataxD <= "0000" & servosReg(20)(11 downto 0);
+ -- 0x1200002A servo 21
+ when "0000000101010" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 21
+ DataxD <= "0000" & servosReg(21)(11 downto 0);
+ -- 0x1200002C servo 22
+ when "0000000101100" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 22
+ DataxD <= "0000" & servosReg(22)(11 downto 0);
+ -- 0x1200002E servo 23
+ when "0000000101110" =>
+ -- Envoi sur le bus de donnees \xB5P du registre du servo 23
+ DataxD <= "0000" & servosReg(23)(11 downto 0);
+ -- 0x12000030 Registre de validation LSB
+ when "0000000110000" =>
+ -- Envoi sur le bus de donnees \xB5P du registre de validation LSB
+ DataxD <= enableReg(15 downto 0);
+ -- 0x12000032 Registre de validation MSB
+ when "0000000110010" =>
+ -- Envoi sur le bus de donnees \xB5P du registre de validation LSB
+ DataxD <= enableReg(31 downto 16);
+ when others =>
+ DataxD <= (others => '0');
+ end case;
+ else
+ -- Haute impedance si acces autre qu'en lecture
+ DataxD <= (others => 'Z');
+ end if;
+ end process registerRead;
+end architecture structural;
Added: trunk/firmware/servo/pwm_module.vhd
===================================================================
--- trunk/firmware/servo/pwm_module.vhd (rev 0)
+++ trunk/firmware/servo/pwm_module.vhd 2008-02-10 14:33:27 UTC (rev 760)
@@ -0,0 +1,77 @@
+----------------------------------------------------------------------------------
+-- Company: Armadeus Project
+-- Engineer: Yvan ROCH
+--
+-- Create Date: 2007-12-05
+-- Design Name:
+-- Module Name: PWM_MODULE - Behavioral
+-- Project Name: SERVO
+-- Target Devices: Spartan3 Armadeus
+-- Tool versions: ISE 9.2.02i
+-- Description: PWM signal generator
+--
+-- Dependencies:
+--
+-- Revision:
+-- Revision 0.01 - File Created
+-- Additional Comments:
+--
+------------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+entity PWM_MODULE is
+ Port (
+ -- Compteur externe de 16 bits cadencer a 4MHz: un cycle complet du compteur
+ -- dure 16.384 ms, c'est la dur\xE9e entre 2 implusions
+ count : in std_logic_vector(15 downto 0);
+ -- signal servosReg(X) copie dans pwmValue
+ servosReg : in std_logic_vector( 11 downto 0);
+ -- signal enableReg(X) copie dans enable
+ enableReg: in std_logic;
+ -- sortie pwm
+ pwmOut : out std_logic;
+ -- le signal writeValue valide l'ecriture de servosReg dans pwmValue et enableReg dans
+ -- enable a un instant ou la sortie PWM est a zero.
+ -- Ainsi la generation de l'impulsion n'est pas perturbee par le changement
+ -- de valeur de servosReg et enableReg
+ writeValue : in std_logic);
+end PWM_MODULE;
+
+architecture Behavioral of PWM_MODULE is
+ -- Valeur interne pwmValue : registre de 12 bits.
+ signal pwmValue : std_logic_vector(11 downto 0) := "000000000000";
+ -- Validation de la sortie PWM
+ signal enable: std_logic := '0';
+begin
+
+ -- Ecriture dans les registres du module
+ process(writeValue)
+ begin
+ if (writeValue'event and writeValue='1') then
+ -- Sur le front montant de writeValue memorisation
+ -- de servosReg dans pwmValue et enableReg dans enable
+ pwmValue <= servosReg;
+ enable <= enableReg;
+ end if;
+ end process;
+
+ -- Generation du signal PWM
+ pwmOut <= '0' when (enable = '0') else -- sortie a 0 si servo devalide
+ -- Generation de l'impulsion de 0.5 ms commune a toute les valeurs
+ -- 1111100000110000b=63536
+ -- 65536-63536=2000 2000 cycle a 4MHz=0.5ms
+ -- Cela corresponde au debut de generation de l'impulsion
+ '1' when (count > "1111100000110000") else -- Count of 63536
+ -- Multiplication de pwmValue par 2 (decalage a gauche de 1)
+ -- pour pwmValue=0 position extreme avec une impulsion de 0+0.5=0.5ms
+ -- pour pwmValue=4000 position extreme avec une impulsion de 2+0.5=2.5ms
+ -- pwmValue= temps_impulsion(ms).2.10^6
+ -- Quand le compteur est depasse: fin de l'implusion
+ '0' when (count > ("000" & pwmValue(11 downto 0) & "0")) else
+ -- le compteur vaut entre 0 et pwmValue: generation de l'impulsion
+ '1';
+end Behavioral;
Added: trunk/firmware/servo/servo.ucf
===================================================================
--- trunk/firmware/servo/servo.ucf (rev 0)
+++ trunk/firmware/servo/servo.ucf 2008-02-10 14:33:27 UTC (rev 760)
@@ -0,0 +1,65 @@
+#PACE: Start of Constraints generated by PACE
+
+#PACE: Start of PACE I/O Pin Assignments
+NET "AddrxDI<0>" LOC = "P21" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<10>" LOC = "P33" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<11>" LOC = "P35" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<12>" LOC = "P36" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<1>" LOC = "P23" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<2>" LOC = "P24" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<3>" LOC = "P25" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<4>" LOC = "P26" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<5>" LOC = "P27" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<6>" LOC = "P28" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<7>" LOC = "P30" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<8>" LOC = "P31" | IOSTANDARD = LVCMOS33 ;
+NET "AddrxDI<9>" LOC = "P32" | IOSTANDARD = LVCMOS33 ;
+NET "clkInImx96MHz" LOC = "P55" | IOSTANDARD = LVCMOS33 ;
+NET "CSxBI" LOC = "P59" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<0>" LOC = "P1" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<10>" LOC = "P13" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<11>" LOC = "P14" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<12>" LOC = "P15" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<13>" LOC = "P17" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<14>" LOC = "P18" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<15>" LOC = "P20" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<1>" LOC = "P2" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<2>" LOC = "P4" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<3>" LOC = "P5" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<4>" LOC = "P6" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<5>" LOC = "P7" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<6>" LOC = "P8" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<7>" LOC = "P10" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<8>" LOC = "P11" | IOSTANDARD = LVCMOS33 ;
+NET "DataxD<9>" LOC = "P12" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<0>" LOC = "P87" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<10>" LOC = "P98" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<11>" LOC = "P97" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<12>" LOC = "P103" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<13>" LOC = "P102" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<14>" LOC = "P100" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<15>" LOC = "P107" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<16>" LOC = "P105" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<17>" LOC = "P104" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<18>" LOC = "P128" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<19>" LOC = "P127" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<1>" LOC = "P86" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<20>" LOC = "P108" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<21>" LOC = "P129" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<22>" LOC = "P130" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<23>" LOC = "P125" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<2>" LOC = "P85" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<3>" LOC = "P92" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<4>" LOC = "P90" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<5>" LOC = "P89" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<6>" LOC = "P96" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<7>" LOC = "P95" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<8>" LOC = "P93" | IOSTANDARD = LVCMOS33 ;
+NET "pwmOut<9>" LOC = "P99" | IOSTANDARD = LVCMOS33 ;
+NET "RDxBI" LOC = "P63" | IOSTANDARD = LVCMOS33 ;
+NET "WRxBI" LOC = "P60" | IOSTANDARD = LVCMOS33 ;
+#PACE: Start of PACE Area Constraints
+
+#PACE: Start of PACE Prohibit Constraints
+
+#PACE: End of Constraints generated by PACE
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|