Cours:TP printempsM4209 TP 6c Corr

De troyesGEII
Aller à : navigation, rechercher

Il s’agit d’une page protégée.

Ceci est le corrigé du TP Réalisation du réglage de l'heure réveil par le processeur.

Puisqu'il s'agit d'un processeur, nous donnons trois fichiers de correction :

  • fichier microcontroleur.vhd
  • fichier lcd16x2_ctrl_demo.vhd
  • un fichier d'exemple d'utilisation en C

Fichier microcontroleur.vhd

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    08:57:48 08/26/2014 
-- Design Name: 
-- Module Name:    microcontroleur - microcontroleur_architecture 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- 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;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity microcontroleur is
    Port ( clk : in  STD_LOGIC;
           Rst : in  STD_LOGIC;
			  sw : in STD_LOGIC_VECTOR (7 downto 0);
			  In_PINB : in STD_LOGIC_VECTOR (7 downto 0);
           Led : out  STD_LOGIC_VECTOR (7 downto 0);
           lcd_e  : out std_logic;
           lcd_rs : out std_logic;
           lcd_rw : out std_logic;
           lcd_db : out std_logic_vector(7 downto 4)
			  );
end entity microcontroleur;

architecture microcontroleur_architecture of microcontroleur is
--Registres et PORTs de l'ATTiny861
constant OCR1A : std_logic_vector(5 downto 0) := "101101";
constant OCR1B : std_logic_vector(5 downto 0) := "101100";
constant PORTA : std_logic_vector(5 downto 0) := "011011";
constant DDRA : std_logic_vector(5 downto 0) := "011010";
constant PINA : std_logic_vector(5 downto 0) := "011001";
constant PORTB : std_logic_vector(5 downto 0) := "011000";
constant DDRB : std_logic_vector(5 downto 0) := "010111";
constant PINB : std_logic_vector(5 downto 0) := "010110";
constant ADCH : std_logic_vector(5 downto 0) := "000101";
constant ADCL : std_logic_vector(5 downto 0) := "000100";
--Registres non présents dans l'ATTiny861
constant UDR : std_logic_vector(5 downto 0) := "000011";
constant UCSRA : std_logic_vector(5 downto 0) := "000010";
constant UCSRB : std_logic_vector(5 downto 0) := "000001";
	component mcu_core is
		Port (
			Clk	: in std_logic;
			Rst	: in std_logic; -- Reset core when Rst='1'
			En		: in std_logic; -- CPU stops when En='0', could be used to slow down cpu to save power
			-- PM
			PM_A		: out std_logic_vector(15 downto 0);
			PM_Drd	: in std_logic_vector(15 downto 0);
			-- DM
			DM_A		: out std_logic_vector(15 downto 0); -- 0x00 - xxxx
			DM_Areal	: out std_logic_vector(15 downto 0); -- 0x60 - xxxx (same as above + io-adr offset)
			DM_Drd	: in std_logic_vector(7 downto 0);
			DM_Dwr	: out std_logic_vector(7 downto 0);
			DM_rd		: out std_logic;
			DM_wr		: out std_logic;
			-- IO
			IO_A		: out std_logic_vector(5 downto 0); -- 0x00 - 0x3F
			IO_Drd	: in std_logic_vector(7 downto 0);
			IO_Dwr	: out std_logic_vector(7 downto 0);
			IO_rd		: out std_logic;
			IO_wr		: out std_logic;
			-- OTHER
		   OT_FeatErr	: out std_logic; -- Feature error! (Unhandled part of instruction)
		   OT_InstrErr	: out std_logic -- Instruction error! (Unknown instruction)
		);
	end component mcu_core;
	--PM
	component pm  is
		Port (
				Clk	: in std_logic;
				rst	: in std_logic; -- Reset when Rst='1'
				-- PM
				PM_A		: in std_logic_vector(15 downto 0);
				PM_Drd	: out std_logic_vector(15 downto 0)
		);
	end component pm;	

  component dm is
    Port ( clk : in  STD_LOGIC;
           addr : in  STD_LOGIC_VECTOR (15 downto 0);
           dataread : out  STD_LOGIC_VECTOR (7 downto 0);
           datawrite : in  STD_LOGIC_VECTOR (7 downto 0);
           rd : in  STD_LOGIC;
           wr : in  STD_LOGIC);
  end component dm;
  
  component lcd16x2_ctrl_demo is
  port (
    clk    : in  std_logic;
	 Armkey    : in std_logic;
	 HHMMAlarm : in std_logic_vector(15 downto 0);
	 HHMMCourante : out std_logic_vector(15 downto 0);
    lcd_e  : out std_logic;
    lcd_rs : out std_logic;
    lcd_rw : out std_logic;
    lcd_db : out std_logic_vector(7 downto 4);
	 led_out : out std_logic);
end component lcd16x2_ctrl_demo;

	signal PM_A		: std_logic_vector(15 downto 0);
	signal PM_Drd	: std_logic_vector(15 downto 0);
	-- DM
	signal DM_A			: std_logic_vector(15 downto 0); -- 0x00 - xxxx
	signal DM_Areal	: std_logic_vector(15 downto 0); -- 0x60 - xxxx (same as above + io-adr offset)
	signal DM_Drd		: std_logic_vector(7 downto 0);
	signal DM_Dwr		: std_logic_vector(7 downto 0);
	signal DM_rd		: std_logic;
	signal DM_wr		: std_logic;
	-- IO
	signal IO_A		: std_logic_vector(5 downto 0); -- 0x00 - 0x3F
	signal IO_Drd	: std_logic_vector(7 downto 0);
	signal IO_Dwr	: std_logic_vector(7 downto 0);
	signal IO_rd	: std_logic;
	signal IO_wr	: std_logic;

	signal IO_DrdA	: std_logic_vector(7 downto 0);
	signal IO_DrdB	: std_logic_vector(7 downto 0);

	signal s_HHMMAlarm, s_HHMMCourante : std_logic_vector(15 downto 0);
	       
begin

	core : mcu_core Port map (
		Clk	=> clk,
		Rst	=> Rst,
		En		=> '1',
		-- PM
		PM_A		=> PM_A,
		PM_Drd	=> PM_Drd,
		-- DM
		DM_A		=> DM_A,
		DM_Areal	=> DM_Areal,
		DM_Drd	=> DM_Drd,
		DM_Dwr	=> DM_Dwr,
		DM_rd		=> DM_rd,
		DM_wr		=> DM_wr,
		-- IO
		IO_A		=> IO_A,
		IO_Drd	=> IO_Drd,
		IO_Dwr	=> IO_Dwr,
		IO_rd		=> IO_rd,
		IO_wr		=> IO_wr,
		-- OTHER
		OT_FeatErr => open,
		OT_InstrErr	=> open
	);

	prgmem : pm port map (
			Clk	=> clk,
			Rst	=> '0',
			-- PM
			PM_A		=> PM_A,
			PM_Drd	=> PM_Drd
	);
	
	datamem : dm port map (
           clk => clk,
           addr => DM_A,
           dataread  => DM_Drd,
           datawrite => DM_Dwr,
           rd => DM_rd, 
           wr =>	DM_wr
	);
	
	lcdmanager: lcd16x2_ctrl_demo port map (
    clk    => clk,
	 Armkey    => '0',
	 HHMMAlarm => s_HHMMAlarm,
	 HHMMCourante => s_HHMMCourante,
    lcd_e  => lcd_e,
    lcd_rs => lcd_rs,
    lcd_rw => lcd_rw,
    lcd_db => lcd_db,
	 led_out => open);
	
	-- IO write process
--
    iowr: process(CLK)
    begin
        if (rising_edge(CLK)) then
            if (IO_wr = '1') then
                case IO_A is
		 -- addresses for tiny861 device (use io.h).
       --
                    when PORTA  => -- PORTA=X"1B" (0X3B)
                                   Led <= IO_Dwr;
		              when  PORTB => -- PORTB=X"18" (0X38)
			                          s_HHMMAlarm(7 downto 0) <= IO_Dwr;
                    when  DDRB => -- PORTB=X"17" (0X37)
			                          s_HHMMAlarm(15 downto 8) <= IO_Dwr;
--                    when  ADCL => -- PORTB=X"18" (0X38)
--			                          s_HHMMAlarm(23 downto 16) <= IO_Dwr;
--                    when  ADCH => -- PORTB=X"17" (0X37)
--			                          s_HHMMAlarm(31 downto 24) <= IO_Dwr;												  
                    when others =>
                end case;
            end if;
        end if;
    end process;
	 
-- IO read process
--
    iord: process(IO_rd,IO_A,In_PINB,sw)
    begin
        -- addresses for tinyX6 device (use iom8.h).
        --
		  if IO_rd = '1' then
          case IO_A is
			   when  PINA => IO_Drd <= sw;  -- PINA=X"19" (0X39)
            when  PINB => IO_Drd <= In_PINB;  -- PINB=X"16" (0X36)
				when  PORTB => IO_Drd <= s_HHMMCourante(7 downto 0);  -- PORTB=X"18" (0X38)
				when  DDRB => IO_Drd <= s_HHMMCourante(15 downto 8);  -- PINB=X"17" (0X37)
            when others => IO_Drd <= X"AA";
          end case;
		  end if;
    end process;

end microcontroleur_architecture;

Fichier "lcd16x2_ctrl_demo.vhd"

-------------------------------------------------------------------------------
-- Title      : Synthesizable demo for design "lcd16x2_ctrl"
-- Project    : 
-------------------------------------------------------------------------------
-- File       : lcd16x2_ctrl_tb.vhd
-- Author     :   <stachelsau@T420>
-- Company    : 
-- Created    : 2012-07-28
-- Last update: 2012-07-29
-- Platform   : 
-- Standard   : VHDL'93/02
-------------------------------------------------------------------------------
-- Description: This demo writes writes a "hello world" to the display and
-- interchanges both lines periodically.
-------------------------------------------------------------------------------
-- Copyright (c) 2012 
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2012-07-28  1.0      stachelsau      Created
-------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;

-------------------------------------------------------------------------------

entity lcd16x2_ctrl_demo is
  port (
    clk    : in  std_logic;
	 Armkey    : in std_logic;
	 HHMMAlarm : in std_logic_vector(15 downto 0);
	 HHMMCourante : out std_logic_vector(15 downto 0);
    lcd_e  : out std_logic;
    lcd_rs : out std_logic;
    lcd_rw : out std_logic;
    lcd_db : out std_logic_vector(7 downto 4);
	 led_out : out std_logic);

end entity lcd16x2_ctrl_demo;

-------------------------------------------------------------------------------

architecture behavior of lcd16x2_ctrl_demo is
  component CounterBCD is
    port( EN: in std_logic;
 	   Clock: in std_logic;
 	   Reset: in std_logic;
	   ENO : out std_logic;
 	   Output: out std_logic_vector(3 downto 0));
  end component CounterBCD;
  
  component CounterModulo6 is
    port( EN: in std_logic;
 	   Clock: in std_logic;
 	   Reset: in std_logic;
	   ENO : out std_logic;
 	   Output: out std_logic_vector(3 downto 0));
  end component CounterModulo6;
  
  component SequSonnerie IS
  PORT(                  
        clock,Key,Trip,ena :IN std_logic;
        Ring :OUT std_logic
        );
  END component SequSonnerie;
  -- 
  signal timer : natural range 0 to 5000000 := 0;
  signal eno10Hz, s_eno, s_eno2, s_eno3 : std_logic := '0';
  signal line1 : std_logic_vector(127 downto 0);
  signal line2 : std_logic_vector(127 downto 0);
  signal s_data16 :  std_logic_vector(15 downto 0);
  signal s_eno2_heure : std_logic_vector(16 downto 8);
  signal s_reset : std_logic;
  signal egalite : std_logic;
  
  -- component generics
  constant CLK_PERIOD_NS : positive := 20;  -- 50 Mhz

  -- component ports
  signal rst          : std_logic;
  signal line1_buffer : std_logic_vector(127 downto 0);
  signal line2_buffer : std_logic_vector(127 downto 0);

begin  -- architecture behavior

  -- component instantiation
  DUT : entity work.lcd16x2_ctrl
    generic map (
      CLK_PERIOD_NS => CLK_PERIOD_NS)
    port map (
      clk          => clk,
      rst          => rst,
      lcd_e        => lcd_e,
      lcd_rs       => lcd_rs,
      lcd_rw       => lcd_rw,
      lcd_db       => lcd_db,
      line1_buffer => line1_buffer,
      line2_buffer => line2_buffer);

  rst <= '0';

  -- see the display's datasheet for the character map
  line1(127 downto 120) <= X"20"; 
  line1(119 downto 112) <= X"20";
  line1(111 downto 104) <= X"20";  
  line1(103 downto 96)  <= X"20";  
  line1(95 downto 88)   <= X"20";  
  line1(87 downto 84)   <= X"3";
  line1(83 downto 80)   <= s_data16(15 downto 12);
  line1(79 downto 76)   <= X"3";
  line1(75 downto 72)   <= s_data16(11 downto 8);
  line1(71 downto 64)   <= X"3A"; 
  line1(63 downto 60)   <= X"3";
  line1(59 downto 56)   <= s_data16(7 downto 4); 
  line1(55 downto 52)   <= X"3";
  line1(51 downto 48)   <= s_data16(3 downto 0);  
  line1(47 downto 40)   <= X"20";  
  line1(39 downto 32)   <= X"20";  
  line1(31 downto 24)   <= X"20";  
  line1(23 downto 16)   <= X"20";  
  line1(15 downto 8)    <= X"20";
  line1(7 downto 0)     <= X"20";

  line2(127 downto 120) <= X"20";
  line2(119 downto 112) <= X"20";
  line2(111 downto 104) <= X"20";
  line2(103 downto 96)  <= X"20";
  line2(95 downto 88)   <= X"20";
  line2(87 downto 84)   <= X"3";
  line2(83 downto 80)   <= HHMMAlarm(15 downto 12);
  line2(79 downto 76)   <= X"3";
  line2(75 downto 72)   <= HHMMAlarm(11 downto 8);
  line2(71 downto 64)   <= X"3A"; 
  line2(63 downto 60)   <= X"3";
  line2(59 downto 56)   <= HHMMAlarm(7 downto 4); 
  line2(55 downto 52)   <= X"3";
  line2(51 downto 48)   <= HHMMAlarm(3 downto 0);  
  line2(47 downto 40)   <= X"20";
  line2(39 downto 32)   <= X"20";
  line2(31 downto 24)   <= X"20";
  line2(23 downto 16)   <= X"20";
  line2(15 downto 8)    <= X"20";
  line2(7 downto 0)     <= X"20";

  line1_buffer <= line1; -- when switch_lines = '1' else line1;
  line2_buffer <= line2; -- when switch_lines = '1' else line2;

  -- timer 10 Hz
  process(clk)
  begin
    if rising_edge(clk) then
      if timer = 0 then
        timer <= 5000000;
      else
        timer <= timer - 1;
      end if;
    end if;
      
  end process;
  eno10Hz <= '1' when timer = 0 else
            '0';
				
				
  MNUnit: CounterBCD port map( 
    EN => eno10Hz,
 	 Clock => clk,
 	 Reset => '0',
	 ENO => s_eno,
 	 Output => s_data16(3 downto 0));
  MNDiz: CounterModulo6 port map( 
    EN => s_eno,
 	 Clock => clk,
 	 Reset => '0',
	 ENO => s_eno2,
 	 Output => s_data16(7 downto 4));
  HHUnit: CounterBCD port map( 
    EN => s_eno2,
 	 Clock => clk,
 	 Reset => s_reset,
	 ENO => s_eno3,
 	 Output => s_data16(11 downto 8));
  HHDiz: CounterBCD port map( 
    EN => s_eno3,
 	 Clock => clk,
 	 Reset => s_reset,
	 ENO => open,
 	 Output => s_data16(15 downto 12));	 	 				
-- reset quand 23 est detecte	par rebouclage
    s_eno2_heure <= s_eno2 & s_data16(15 downto 8);
    with s_eno2_heure select
	   s_reset <= '1' when "100100011",
                 '0' when others;
  egalite <= '1' when HHMMAlarm = s_data16 else
            '0';
  SequenceurPourSonnerie:	SequSonnerie PORT MAP(                  
        clock => clk,
		  Key=> ArmKey,
		  Trip => egalite,
		  ena => eno10Hz,
        Ring => led_out
        );
	HHMMCourante <= s_data16;	  
end architecture behavior;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity CounterBCD is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
	 ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end CounterBCD;
 
architecture Behavioral of CounterBCD is
   signal cmpt: std_logic_vector(3 downto 0);
	signal s_en_cmpt: std_logic_vector(4 downto 0);
begin   process(Clock,Reset)
   begin
      if(rising_edge(Clock)) then
		  if Reset='1' then
         cmpt <= "0000";
 	      elsif EN='1' then
	         if cmpt="1001" then
	            cmpt<="0000";
	         else
	           cmpt <= cmpt + 1;
	         end if;
         end if;
      end if;
   end process;
   Output <= cmpt;
	s_en_cmpt <= en & cmpt;
   with s_en_cmpt select
     ENO <= '1' when "11001",
            '0' when others;
end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- pour les dizaines de minutes
entity CounterModulo6 is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
	 ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end CounterModulo6;
 
architecture Behavioral of CounterModulo6 is
   signal cmpt: std_logic_vector(3 downto 0);
	signal s_en_cmpt: std_logic_vector(4 downto 0);
begin   process(Clock,Reset)
   begin
      if(rising_edge(Clock)) then
		  if Reset='1' then
         cmpt <= "0000";
 	      elsif EN='1' then
	         if cmpt="0101" then
	            cmpt<="0000";
	         else
	           cmpt <= cmpt + 1;
	         end if;
         end if;
      end if;
   end process;
   Output <= cmpt;
	s_en_cmpt <= en & cmpt;
   with s_en_cmpt select
     ENO <= '1' when "10101",
            '0' when others;
end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY SequSonnerie IS
  PORT(                  
        clock,Key,Trip,ena :IN std_logic;
        Ring :OUT std_logic
        );
END SequSonnerie;
ARCHITECTURE arch_SequSonnerie  OF SequSonnerie IS
  TYPE typetat IS (Armed, Off, Ringing); 
  SIGNAL etatp, etatf : typetat;
  BEGIN
-- partie séquentielle
    PROCESS (clock) BEGIN  -- 1er process
	 IF Clock ='1' AND Clock'EVENT THEN
	   IF ena = '1' then
            etatp <= etatf;
		END IF;
     END IF;
    END PROCESS;
    PROCESS(etatp) BEGIN --2eme process
        CASE etatp IS
             WHEN Off => IF key ='1' THEN etatf <= Armed; 
                         ELSE etatf <= Off;
                      END IF;  
             WHEN Armed => IF Key = '0' THEN 
                            etatf <= Off;
	                   ELSIF Trip ='1' THEN 
                             etatf <= Ringing;
	                   ELSE etatf <= Armed;
	                  END IF; 
             WHEN Ringing => IF Key ='0' THEN 
                                 etatf <= Off; 
                            ELSE etatf <= Ringing;
			    END IF; 
	        END CASE;
    END PROCESS;
-- partie combinatoire
   Ring <= '1' WHEN etatp=Ringing ELSE
           '0';
END arch_SequSonnerie;

Fichier d'exemple en C

#include "avr/io.h" 
#undef F_CPU 
#define F_CPU 16000000UL 
#include "util/delay.h" 

//#include <stdio.h>
//#include <string.h>

/*#define UCSRB	_SFR_IO8(0x01) 
#define UCSRA	_SFR_IO8(0x02) 
#define UDR	_SFR_IO8(0x03)
// UCSRA
#define RXC 7
#define TXC 6
#define UDRE 5
//UCSRB
#define RXEN 4
#define TXEN 3
*/
void incrementBCD(uint16_t *cnt);
void decrementBCD(uint16_t *cnt);
void incrementHHMM(uint16_t *hh_mm);
void decrementHHMM(uint16_t *hh_mm);
 
int main (void) {
   uint8_t ch=128, switchs;
   uint16_t heure_courante, heure_reveil = 0; 
   while(1) { 
   // echo simple
   //  PORTA = ch;
     ch >>= 1; 
     if (ch == 0) ch = 128;
     switchs = PINA;
     if ((switchs & 0x03) == 3)
       decrementHHMM(&heure_reveil);
     if ((switchs & 0x03) == 2)
       incrementHHMM(&heure_reveil);

     PORTB = heure_reveil & 0x00FF;
     DDRB = (heure_reveil & 0xFF00)>>8;
     heure_courante = DDRB;
     heure_courante <<= 8;
     heure_courante += PORTB;
     if ((switchs & 0x04) == 0x04) {
        // a remplacer par == mais pour nos tests rapides ...
        if (heure_courante > heure_reveil) 
          PORTA = 0xFF;
     } else 
        PORTA = 0; 
     _delay_ms(300); // on défiler les valeurs     
   } 
   return 0; 
 }

void incrementBCD(uint16_t *cnt) { 
  (*cnt)++;    
  if ((*cnt & 0x000F) > 0x0009) *cnt += 6; 
  if ((*cnt & 0x00F0) > 0x0090) *cnt += 0x0060;
  if ((*cnt & 0x00F0) > 0x0900) *cnt += 0x0600; 
  if ((*cnt & 0x00F0) > 0x9000) *cnt += 0x6000; 
} 

void decrementBCD(uint16_t *cnt) { 
  (*cnt)--;    
  if ((*cnt & 0x000F) == 0x000F) *cnt -= 6; 
  if ((*cnt & 0x00F0) == 0x00F0) *cnt -= 0x0060; 
  if ((*cnt & 0x0F00) == 0x0F00) *cnt -= 0x0600; 
  if ((*cnt & 0xF000) == 0xF000) *cnt -= 0x6000; 
}

void incrementHHMM(uint16_t *hh_mm) {
  (*hh_mm)++;
      if ((*hh_mm & 0x000F) > 0x0009)
      *hh_mm += 0x0006;
      if ((*hh_mm & 0x00F0) > 0x0050)
      *hh_mm += 0x00A0;
      if ((*hh_mm & 0x0F00) > 0x0900)
      *hh_mm += 0x0600;
      if ((*hh_mm & 0xFF00) > 0x2300)
      *hh_mm = 0x0000;
}

void decrementHHMM(uint16_t *hh_mm) {
  (*hh_mm)--;
      if ((*hh_mm & 0x000F) == 0x000F)
      *hh_mm -= 0x0006;
      if ((*hh_mm & 0x00F0) == 0x00F0)
      *hh_mm -= 0x00A0;
      if ((*hh_mm & 0x0F00) == 0x0F00)
      *hh_mm -= 0x0600;
      if ((*hh_mm & 0xFFFF) > 0x2359)
      *hh_mm = 0x2359;
}