Você está na página 1de 29

Tutorial

 -­‐  Xilinx  ISE

Universidade  Federal  do  Rio  de  Janeiro


Escola  Politécnica
Departamento  de  Eletrônica  e  Computação

 
       
Autores:                 Orientador:
Artur  Lemos               Mário  Vaz
Ioav  Lichtenstein
Thiago  Lobo
Índice:
1.  Introdução                   3
2.  Instalação                     4
3.  Criando  um  novo  projeto             5
4. VHDL  Básico                   8
5. Simulando  um  projeto               15
6.  Criando  um  DCM                 23
7.  Implementando  um  projeto  na  FPGA                      26
8.  Exemplos  de  Código               27

2
1.  Introdução
  O  ISE  (Integrated  Software  Environment)  é  um  software  
criado  pela  Xilinx  para  síntese  e  análise  de  modelos  HDL.  O  
usuário  poderá  escrever,  compilar,  realizar  análises  
temporais  (utilizando  diferentes  estímulos  como  entrada)  e/
ou  configurar  FPGA’s  com  o  modelo  criado.
  Este  tutorial  visa  fornecer  ao  usuário  uma  visão  geral  do  
software,  mostrando,  de  forma  simples,  desde  a  ativação  do  
programa  até  a  compilação,  visualização  de  diagramas  RTL  e  
configuração  da  FPGA  Spartan  3AN  com  códigos  VHDL.
  Desenvolveremos  o  tutorial  baseando-­‐nos  num  módulo  
divisor  de  freqüência,  e  forneceremos  outros  exemplos  de  
código  na  última  sessão.

3
2.  Instalação
  Para  ativar  o  ISE,  deve-­‐se  baixar  os  arquivos  no  link  
https://www.del.ufrj.br/pastas-­‐das-­‐disciplinas/eel480  -­‐
sistemas-­‐digitais,  garantir  que  estão  na  pasta  ~/Downloads  e  
executar  a  seguinte  instrução  no  Terminal:
  cd  ;  tar  xvf  ∼/Downloads/Xilinx.tar  ;  ./ise.sh
  Feito  isso,  o  ISE  deverá  estar  ativado  e  para  executá-­‐lo,  
deve-­‐se  utilizar  o  seguinte  comando,  também  no  Terminal:
  ise  &
  O  que  nos  leva  à  tela  principal  do  programa:

4
3.  Criando  um  novo  projeto
  Na  tela  principal  do  ISE,  devemos  começar  pelo  menu  
“File  >  New  Project”  e  a  janela  “New  Project  Wizard”  será  
aberta.
 
Campos:
“Name”  -­‐  nome  do  projeto
“Location”  -­‐  localização  onde  o  projeto  será  salvo*
“Description”  -­‐  descrição  do  projeto

*  -­‐  utilizaremos  a  pasta  /tmp,  pois  eventualmente,  o  ISE  


pode  gerar  arquivos  de  projeto  muito  grandes,  os  quais  
excederiam  o  limite  por  usuário  da  rede.  Para  garantir  que  os  
arquivos  sejam  guardados,  devemos  utilizar  o  comando  
Archive,  como  mostraremos  posteriormente.
 

5
  Feito  isso,  clicar  em  “Next”.  Agora,  devemos  escolher  
outros  parâmetros  de  projeto:
“Evaluation  Development  Board”  -­‐  Spartan  3AN  Starter  Kit
“Synthesis  Tool”  -­‐  XST
“Prefered  Language”  -­‐  VHDL
“VHDL  Source  Analysis  Standard”  -­‐  VHDL-­‐93

  Após  clicar,  mais  uma  vez,  em  “Next”,  uma  janela  que  
resume  os  parâmetros  do  projeto  será  exibida.  Confira  os  
dados  e  caso  estejam  corretos,  clique  em  “Finish”.
   Agora,  temos  um  projeto  (.xise)  pronto,  basta  adicionar    
códigos-­‐fonte  VHDL  e  poderemos  trabalhar  com  os  
modelos.  Para  importar  um  código  VHDL  já  escrito,  devemos    
acessar  o  menu  “Project  >  Add  Copy  of  Source”,  navegar  até  
o  arquivo  e  selecioná-­‐lo.  Isso  copiará  o  arquivo  para  o  
workspace  do  projeto  e  permitirá  sua  edição.  Sempre  que  a  
edição  dos  arquivos  estiver  concluída,  devemos  utilizar  o  
menu  “Project  >  Archive”,  para  salvar  o  projeto  na  pasta  do  

6
usuário  em  formato  .zip.  Para  utilizar  esse  projeto  
posteriormente,  basta  descompactar  o  .zip  gerado  dentro  da  
pasta  /tmp  e  abri-­‐lo  na  primeira  tela  do  ISE  (“Open  Project”).

7
4.  VHDL  Básico
  VHDL  é  uma  linguagem  de  descrição  de  hardware  que  
foi  inicialmente  utilizada  para  documentar  componentes  
digitais  e  acabou  sendo  aproveitada  para  simulações/
implementações  em  FPGA  desses  mesmos  componentes.
  Um  arquivo  VHDL  deve  conter,  no  mínimo,  uma  entity  e  
uma  architecture.  
  A  entity    consiste  na  descrição  da  interface  do  módulo  
como  uma  caixa  preta:  especificando  apenas  as  entradas  e  
saídas.
  A  architecture  descreve  o  funcionamento  do  módulo,  
propriamente  dito.  Costumamos  separar  architectures  em  
duas  classes:  comportamentais  e  estruturais.  As  
comportamentais  servem  para  definir  como  um  módulo  
funcionará  e  as  estruturais  servem  para  definir  como  um  
módulo  de  alta  hierarquia  interliga  diferentes  módulos  
“menores”  (o  que  não  deixa  de  ser  seu  funcionamento).
  A  utilização  de  módulos  já  prontos  dentro  de  uma  
architecture  se  assemelha  à  instanciação  de  um  objeto  em  
uma  linguagem  Orientada  a  Objetos:  especifica-­‐se  o  tipo  do  
objeto  (sua  Entity),  escolhe-­‐se  um  nome  e  mapeia-­‐se  suas  
entradas  e  saídas  (semelhante  ao  construtor  de  classes  em  
Java).
  Dentro  da  architecture  utilizamos  sinais  (signals)  para  
intercomunicar  módulos.  É  aplicável  um  paralelo  com  as  
variáveis  de  um  programa  em  Java.
  Comentários  são  feitos  utilizando-­‐se  um  “-­‐-­‐”,  por  
exemplo:
  -­‐-­‐  Isso  é  um  comentário  e  não  será  utilizado  na  síntese
 

8
  Segue  um  exemplo  básico:  uma  porta  lógica  AND:
1. -­‐-­‐  importando  std_logic  da  biblioteca  IEEE
2. library  IEEE;
3. use  IEEE.std_logic_1164.all;
4.  
5. -­‐-­‐  essa  é  a  entidade  (entity)
6. entity  ANDGATE  is
7.    port  (  
8.        I1  :  in  std_logic;
9.        I2  :  in  std_logic;
10.        O    :  out  std_logic);
11. end  entity  ANDGATE;
12.  
13. -­‐-­‐  essa  é  a  arquitetura  comportamental  (architecture)
14. architecture  behavioral  of  ANDGATE  is
15. begin
16.    O  <=  I1  and  I2;
17. end  architecture  behavioral;

  Como  podemos  ver,  a  leitura  do  bloco  “entity”  permite  


imaginarmos  o  seguinte:
 

I1 I1

I2 ANDGATE
O
 

  Depois,  em  architecture,  o  funcionamento  do  bloco  é  


descrito:  a  saída  O  recebe  a  operação  bit-­‐a-­‐bit  AND  entre  as  
entradas  I1  e  I2.  A  operação  AND  foi  incluída  quando  
importamos  a  biblioteca  IEEE.

9
  Agora,  podemos  analisar  o  divisor  de  freqüência  clk_div:

18. library  IEEE;


19. use  IEEE.STD_LOGIC_1164.ALL;
20. use  ieee.numeric_std.ALL;
21.  
22. entity  clk_div  is
23.      generic  (n  :  integer  :=  4);
24.      port  (clk_in  :  in        std_logic;  
25.                  div        :  out      std_logic;
26.                  div2      :  out      std_logic  );
27. end  clk_div;
28.  
29. architecture  divide  of  clk_div  is
30. signal  cnt,  cnt1  :  integer  :=  0;
31. signal  div_temp,  div_temp2  :  std_logic  :=  '0';
32.  
33. begin
34. div  <=  div_temp;
35. div2  <=  div_temp2;
36. process  (clk_in)  begin
37.                if  (clk_in'event  and  clk_in  =  '1')  then
38.                                if  cnt  >=  n  then
39.                                                div_temp  <=  not(div_temp);
40.                                                cnt  <=  1;
41.                                else        
42.                                                div_temp  <=  div_temp;
43.                                                cnt  <=  cnt  +  1;
44.                                end  if;
45.                end  if;
46.                if  (clk_in'event  and  clk_in  =  '0')  then
47.                                if  cnt1  >=  n  then
48.                                                cnt1  <=  1;  
49.                                                div_temp2  <=  '1';
50.                                else        
51.                                                div_temp2  <=  '0';
52.                                                cnt1  <=  cnt1  +  1;
53.                                end  if;
54.                end  if;
55.                end  process;
56. end  divide;
 
  Como  podemos  ver,  o  módulo  clk_div  é  descrito  por  
uma  entrada  (clk_in)  e  duas  saídas  (div1  e  div2).  O  generic  n  :  
integer  :=  4  é  equivalente  a  um  #define  em  C.  n  será  

10
substituído  em  todos  os  lugares  que  aparece  no  código  por  
4.  Trata-­‐se  de  uma  constante.  Dentro  da  architecture,  vemos  
um  process,  que  é  como  uma  função  em  C.  Todo  processo  
leva  uma  lista  de  sensibilidade,  que  no  caso  é  (clk_in).  Isso  
indica  que  sempre  que  clk_in  for  atualizado,  o  process  será  
executado.  Há,  também,  4  signals:  2  contadores  e  2  
temporários  que  são  mapeados  às  saídas  do  bloco,  como  
indicam  as  linhas:  

57. div  <=  div_temp;


58. div2  <=  div_temp2;

  Sabendo-­‐se  disso,  podemos  realizar  o  resto  da  análise  


como  em  qualquer  linguagem  de  programação.  
Perceberemos  que  div  é  simplesmente  clk_in  dividido  por  n  e  
que  div2  é  um  clock  cujo  período  é  o  mesmo  de  div,  porém  
seu  duty-­‐cycle  (tempo  em  nível  alto)  é  de  25%,  ao  contrário  
dos  50%  em  clk_in  e  div.

11
  Agora,  podemos  analisar  o  outro  módulo,  base_tempo,  
que  utiliza  o  módulo  clk_div  para  dividir  a  frequência  do  sinal  
de  entrada  clk.  Vale  ressaltar  o  fato  de  que  um  DCM  (Digital  
Clock  Manager  foi  necessário,  voltaremos  a  falar  sobre  ele  na  
sessão  5):
59. library  IEEE;
60. use  IEEE.STD_LOGIC_1164.ALL;
61. use  ieee.numeric_std.ALL;
62. library  UNISIM;
63. use  UNISIM.Vcomponents.ALL;
64.  
65. entity  base_tempo  is
66.      generic  (n:  integer  :=  2);
67.      port  (clk              :  in    std_logic;
68.                  clk_out      :  out  std_logic;
69.                  clk_out_2  :  out  std_logic;
70.                  locked        :  out  std_logic);
71. attribute  LOC  :  string  ;
72. attribute  LOC  of  clk  :  signal  is  "E12";
73. attribute  LOC  of  locked  :  signal  is  "W21";
74. attribute  LOC  of  clk_out  :  signal  is  "Y22";
75. attribute  LOC  of  clk_out_2  :  signal  is  "Y18";
76. end  entity;
77.  
78.  
79. architecture  estrutural  of  base_tempo  is
80. component  clk_div
81.    port  (clk_in    :  in    std_logic;  
82.                div          :  out  std_logic;
83.                div2        :  out  std_logic);
84. end  component;
85.  
86. COMPONENT  dcm1
87. PORT(CLKIN_IN  :  IN  std_logic;
88.          CLKFX_OUT  :  OUT  std_logic;
89.          CLKIN_IBUFG_OUT  :  OUT  std_logic;
90.          CLK0_OUT  :  OUT  std_logic;
91.          LOCKED_OUT  :  OUT  std_logic);
92. END  COMPONENT;
93.  
94. signal  clk_int  :  std_logic;
95.  
96.
97.
98.
99.

12
100.begin
101.clk_divider  :  clk_div  port  map  
102.        (clk_in  =>  clk_int,  
103.          div  =>  clk_out,  
104.          div2  =>  clk_out_2);
105.  
106.Inst_dcm1  :  dcm1  PORT  MAP  (
107.                CLKIN_IN  =>  clk,
108.                CLKFX_OUT  =>  clk_int,
109.                CLKIN_IBUFG_OUT  =>  open,
110.                CLK0_OUT  =>  open,
111.                LOCKED_OUT  =>  locked);
112.end  estrutural;

  Começaremos  a  análise  pela  entity:  como  esperado,  há  


uma  entrada  clk  e  duas  saídas  clk_out  e  clk_out_2.  Há  uma  
saída  extra  chamada  locked,  que  simplesmente  diz  se  o  DCM  
está  ou  não  sincronizado.
  As  linhas  113-­‐117  associam  sinais  da  entity  a  
componentes  da  FPGA  na  qual  o  código  será  carregado.  
Exceto  por  “E12”,  todos  os  sinais  são  mapeados  a  LEDS  ou  
contatos,  que  podem  ser  identificados  pelos  mesmos  nomes  
na  placa  física:
113.attribute  LOC  :  string  ;
114.attribute  LOC  of  clk  :  signal  is  "E12";
115.attribute  LOC  of  locked  :  signal  is  "W21";
116.attribute  LOC  of  clk_out  :  signal  is  "Y22";
117.attribute  LOC  of  clk_out_2  :  signal  is  "Y18";
  A  achitecture,  como  de  se  esperar,  é  estrutural,  pois  
base_tempo  trata-­‐se  de  um  módulo  que  unifica  “pequenos”  
módulos  (clk_div  e  dcm1).  Para  instanciarmos  módulos,  
devemos  antes  fazer  uma  declaração  do  tipo  “COMPONENT  
nome  ...  END  COMPONENT;”.  Isso  foi  feito  para  o  clk_div  e  o  
dcm1.
  Feito  isso,  podemos  finalmente  mapear  as  portas  dos  
componentes  (tal  como  inicializar  um  objeto  em  Java  através  
de  seu  construtor)  a  sinais  ou  entradas/saídas  da  entidade.

13
  No  caso,  utilizamos  um  sinal  interno  clk_int,  que  serve  
como  saída  do  dcm1.  Não  podemos  utilizar  diretamente  o  
clock  da  placa  (50mHz),  pois  há  problemas  como  
capacitâncias  parasitas  que  prejudicariam  o  funcionamento  
do  circuito.  De  fato,  resolvemos  esse  problema  através  do  
dcm1,  que  coloca  uma  frequência  menor  em  clk_int  para  que  
essa  seja  utilizada  como  entrada  para  o  clk_div.  As  saídas  do  
clk_div  são  intuitivamente  mapeadas  às  saídas  clk_out  e  
clk_out_2  da  base_tempo.
  Acreditamos  que  a  esse  ponto,  o  leitor  já  adquiriu  certa  
noção  de  código  VHDL  e  de  seu  funcionamento,  sendo  capaz  
de  continuar  por  si  só  utilizando  referências  online  para  
funções  mais  complexas.
 

14
5.  Simulando  um  projeto
  Completados  os  códigos  VHDL,  podemos  realizar  
simulações  e  visualizar  seu  diagrama  RTL  através  do  ISE.  
  Vale  lembrar  que  podemos  ver  erros  de  sintaxe  em  
tempo  real  na  aba  “Errors”,  basta  um  “CTRL  +  s”  para  salvar  
o  código  e  a  janela  será  atualizada  com  os  erros  
encontrados:

  Para  sintetizar  os  arquivos,  devemos  selecionar  a  


“Implementation  View”  em  “Design  >  Hierarchy”.  Feito  isso,  
devemos  clicar  uma  vez  sobre  o  nome  do  componente  que  
será  sintetizado:

15
  Feito  isso,  basta  um  duplo-­‐clique  em  “Synthesize  -­‐  
XST”.  Espere  alguns  instantes  e  verifique  o  log  de  erros  para  
saber  se  a  sintetização  foi  feita  com  sucesso.
  Para  visualizar  o  esquemático  RTL,  basta  expandir  
“Synthesize  -­‐  XST”,  um  dupo-­‐clique  em  “View  RTL  
Schematic”  e  selecionar  “Start  with  a  schematic  of  the  top-­‐
level  block”  no  diálogo  que  será  aberto.

  Com  o  “Top-­‐level  schematic”  aberto,  podemos  dar  


duplos-­‐cliques  de  forma  a  expandir  as  “caixas-­‐pretas”  que  
compoem  o  circuito.
 
  Podemos,  finalmente,  simular  o  código.  Selecione  a  
“Simulation  View”  em  “Design  >  Hierarchy”  e  clique  uma  vez  
sobre  o  nome  do  componente  que  será  simulado.  Feito  isso,  
expanda  “iSIM  simulator”  e  dê  duplos-­‐cliques,  na  sequência,  
em:  “Behavioral  Check  Sintax”  (um  último  teste  de  sintaxe)  e  

16
“Simulate  Behavioral  Model”  (a  simulação  propriamente  
dita).  

  Caso  tudo  corra  bem,  a  janela  do  simulador  (iSim)  será  


aberta:

17
  Agora,  podemos  forçar  um  valor  no  clock  de  forma  a  
observar  a  saída  do  circuito  (que  se  trata  de  um  clk_div).  
Devemos  clicar  com  o  botão  direito  na  variável  desejada  e  
selecionar  “Force  clock”.  Isso  abrirá  uma  janela  com  diversas  
caixas  a  serem  preenchidas:

“Value  Radix”  -­‐  Tipo  de  clock:  binário,  ASCII,  Decimal  etc
“Leading  Edge  Value”  -­‐  Valor  inicial  de  clock
“Trailing  Edge  Value”  -­‐  Valor  final  de  clock
“Starting  at  Time  Offset”  -­‐  Quando  o  clock  começa
“Cancel  After  Time  Offset”  -­‐  Quando  o  clock  termina
“Duty  Cycle  (%)”  -­‐  Razão  entre  Leading  Edge  e  Trailing  Edge
“Period”  -­‐  Auto-­‐explicativo

Preenchendo  da  seguinte  forma,  obtemos  um  período  de  

50mHz.

18
  Agora,  devemos  programar  por  quanto  tempo  a  
simulação  será  executada.  Basta  preencher  a  caixa  de  texto  
na  barra  de  ícones  e  então  clicar  na  setá  para  a  esquerda  
(apagando  a  última  simulação).  Feito  isso,  devemos  clicar  no  
botão  de  play  com  uma  ampulheta  e  na  terceira  lupa  (com  
um  X)  para  ajustar  a  escala  dos  gráficos  ao  tamanho  da  
janela.

  Esse  é  o  resultado  final.  Como  podemos  ver,  o  clock  foi  


devidamente  dividido.

19
  Outra  forma  de  impor  valores  de  clock  e  de  certas  
entradas  é  utilizar  um  TestBench.  Para  tanto,  devemos  
selecionar  a  “Implementation  View”  em  “Design  >  
Hierarchy”,  clicar  com  o  botão  direito  sobre  o  módulo  
principal,  ir  em  “New  >  Source  >  TestBench”.  Devemos  dar  
um  nome  ao  TestBench  (normalmente  adicionando-­‐se  o  
sufixo  _tb  ao  nome  do  componente  original)  e  ao  confirmar  
seremos  levado  à  janela  de  seu  código  fonte  (o  código  
exemplo  foi  usado  em  um  debouncer,  que  será  descrito  na  
última  sessão):

118.LIBRARY  ieee;
119.USE  ieee.std_logic_1164.ALL;
120.  
121.ENTITY  debouncer2_tb  IS
122.END  debouncer2_tb;
123.  
124.ARCHITECTURE  behavior  OF  debouncer2_tb  IS  
125.  
126.        COMPONENT  debouncer2
127.        PORT(
128.                  Clk  :  IN    std_logic;
129.                  Key  :  IN    std_logic;
130.                  pulse  :  OUT    std_logic
131.                );
132.        END  COMPONENT;
133.        
134.  
135.      -­‐-­‐Inputs
136.      signal  Clk  :  std_logic  :=  '0';
137.      signal  Key  :  std_logic  :=  '0';
138.  
139.      -­‐-­‐Outputs
140.      signal  pulse  :  std_logic;
141.  
142.      -­‐-­‐  Clock  period  definitions
143.      constant  Clk_period  :  time  :=  10  ms;
144.  
145.BEGIN
146.  
147.                -­‐-­‐  Instantiate  the  Unit  Under  Test  (UUT)
148.      uut:  debouncer2  PORT  MAP  (
149.                    Clk  =>  Clk,

20
150.                    Key  =>  Key,
151.                    pulse  =>  pulse
152.                );
153.  
154.      -­‐-­‐  Clock  process  definitions
155.      Clk_process  :process
156.      begin
157.                                Clk  <=  '0';
158.                                wait  for  Clk_period/2;
159.                                Clk  <=  '1';
160.                                wait  for  Clk_period/2;
161.      end  process;
162.  
163.  
164.      -­‐-­‐  Stimulus  process
165.      stim_proc:  process
166.      begin                                
167.                Key  <=  '0';
168.            wait  for  Clk_period;
169.                                Key  <=  '1';
170.                                wait  for  Clk_period  *  6;
171.                                Key  <=  '0';
172.                                wait  for  Clk_period  *  4;
173.                                Key  <=  '1';
174.                                wait  for  Clk_period  *  4;
175.                                Key  <=  '0';
176.            wait;
177.      end  process;
178.  
179.END;

  Como  pode-­‐se  ver,  o  módulo  do  exemplo  possui  duas  


entradas  clk  e  key  e  uma  saída  pulse.  Podemos  inicializar  as  
variáveis  como  nas  linhas  136  e  137  e  também  definir  um  
período  para  o  clock.
  Feito  isso,  podemos  implementar  o  Clk_process,  que  
define  como  o  clock  mudará  no  tempo.  No  caso,  como  
podemos  ver,  ele  é  forçado  a  0,  meio  período  é  esperado,  ele  
é  forçado  a  1,  meio  período  é  esperado  e  o  processo  se  
repete,  gerando  uma  onda  quadrada.
  O  mesmo  pode  ser  feito  para  os  estímulos  (as  entradas)  
do  componente  no  processo  stim_proc.  Podemos  usar  a  

21
palavra  reservada  wait  para  definir  os  atrasos  entre  as  
mudanças  de  valores  (que  também  podem  ser  definidas).  
  Com  o  TestBench  feito,  basta  simulá-­‐lo  no  lugar  do  
componente  original  e  teremos  o  processo  automatizado,  
sem  necessidade  de  forçar  clocks  ou  coisas  do  tipo.

22
6.  Criando  um  DCM
  A  criação  de  um  DCM  consiste  nos  seguintes  passos:  
-­‐ Selecionar  o  “Implementation  View”  em  “Design  >  
Hierarchy”
-­‐ Clicar  com  o  botão  direito  no  projeto  e  selecionar  New  
Source
-­‐ Busque  por  DCM  na  barra  de  pesquisa  e  selecione    Single  
DCM_SP  conforme  a  seguinte  imagem:

-­‐ Dê  um  nome  diferente  de  dcm,  tal  como  dcm1  ou  dcm2,  e  
clique  em  Finish
-­‐ Feito  isso,  você  será  levado  à  janela  Xilinx  Clocking  Window
-­‐ Nessa  janela  é  possível  selecionar  os  mais  variados  
parâmetros  para  o  clock  que  o  DCM  transformará.  

23
Selecione  conforme  as  exigências  de  seu  projeto  (como  
multiplicar/dividir  o  clock)

-­‐ Clique  em  Next,  selecione  “Use  Global  Buffers  for  all  
Selected  Clock  Outputs”
-­‐ Clique  em  Next,  selecione  “Show  all  Modifiable  Outputs”  e  
clique  em  Finish

24
-­‐ O  DCM  está  criado,  agora  basta  utilizar  o  código  para  o  
componente  de  DCM  como  mostrado  na  sessão  4.

25
7.  Implementando  um  projeto  na  FPGA
  Caso  os  sinais  da  entity  do  componente  já  estejam  
mapeados  para  partes  da  FPGA,  como  mostrado  na  sessão  
4,  você  está  pronto  para  implementar  o  código  na  placa.  É  
importante,  obviamente,  que  a  placa  esteja  ligada  ao  PC  
pela  interface  USB  e  esteja  devidamente  alimentada.
  Em  primeiro  lugar,  devemos  escolher  a  
“Implementation  View”  em  “Design  >  Hierarchy”,  feito  isso,  
clique  uma  vez  sobre  o  módulo  principal  do  seu  projeto  e  
clique  duas  vezes  sobre  “Configure  Target  Device”.  A  janela  
do  iMPACT  será  aberta.
  Clique  duas  vezes  em  “Boundary  Scan”  e  clique  com  o  
botão  direito  no  espaço  em  branco  e  selecione  “Initialize  
Chain”.  Na  primeira  miniatura  da  FPGA,  carregue  o  
arquivo  .bit  que  correponde  ao  seu  projeto.  Deixei  a  segunda  
em  “bypass”.  Clique  com  o  botão  direito  sobre  a  primeira  
miniatura  e  clique  em  “Program  FPGA  Only”.
  O  programa  deve  estar  carregado  na  placa.  Observe  as  
partes  para  as  quais  os  sinais  foram  mapeados.

26
8.  Exemplos  de  código
Debouncer:

180.LIBRARY  ieee;
181.USE  ieee.STD_LOGIC_1164.all;
182.USE  ieee.STD_LOGIC_UNSIGNED.all;
183.  
184.ENTITY  debouncer2  IS
185.                PORT  (Clk      :  IN    STD_LOGIC;
186.                            Key      :  IN    STD_LOGIC;
187.                            pulse  :  OUT  STD_LOGIC);
188.END  debouncer2;
189.  
190.ARCHITECTURE  shift_register  OF  debouncer2  IS
191.SIGNAL  SHIFT_KEY  :  STD_LOGIC_VECTOR(3  DOWNTO  0)  :=  "1111";
192.  
193.BEGIN
194.PROCESS
195.        BEGIN
196.                            
197.                WAIT  UNTIL  Clk'EVENT  AND  Clk  =  '1';
198.                                
199.                        SHIFT_KEY(2  DOWNTO  0)  <=  SHIFT_KEY(3  DOWNTO  1);
200.                        SHIFT_KEY(3)  <=  NOT  Key;
201.                                
202.                        IF  SHIFT_KEY(3  DOWNTO  0)="0000"  THEN  PULSE  <=  '1';
203.                        ELSE  PULSE  <=  '0';
204.                        END  IF;
205.                                
206.END  PROCESS;
207.END  shift_register;

  Primeiramente,  explicaremos  a  motivação  do  circuito:  


remover  trepidações  transientes  provenientes  de  chaves  
mecânicas.
    O  módulo  possui  duas  entradas  Clk  e    Key  e  uma  saída  
Pulse.  Key  é  o  sinal  proveniente  da  chave  mecânica,  pulse  é  a  
saída  que  corresponde  ao  sinal  da  chave  “corrigido”.  
    O  circuito  funciona  inicializando  o  registrador  para  
“1111”  e  esperando  que  ele  se  torne  “0000”,  para  fazer  pulse  
=  1.  

27
    A  forma  de  atualizar  o  valor  do  registrador  é  ir  
colocando  not  key  no  lado  direito  do  vetor  de  bits  do  
registrador.  Se  por  4  clocks  seguidos,  o  valor  de  key  
amostrado  estiver  em  1,  o  registrador  estará  no  estado  
“0000”  e  pulse  valerá  1,  caso  contrário  pulse  valerá  0.  Isso  faz  
sentido  pois  evita  que  a  saída  seja  atualizada  durante  o  
transiente  da  vibração  da  chave,  fazendo  com  que  ela  só  seja  
ativada  algum  tempo  depois  (o  suficiente  para  que  a  
trepidação  termine).  Logo,  haverá  um  atraso  muito  pequeno  
(porém  detectável  em  osciloscópio)  na  resposta  da  chave.

    A  seguinte  imagem,  adquirida  em  um  osciloscópio  


ligado  à  FPGA  com  o  programa  do  Debouncer  carregado  
demonstra  tal  atraso  e  comprova  o  funcionamento  do  
circuito:

28
    A  curva  mais  baixa  é  key  e  a  mais  alta  é  not  pulse,  
vemos,  portanto,  que  pulse  só  vai  a  1  algum  tempo  depois  de  
key  ter  ido  a  1.  Esse  é  o  tempo  do  transiente  de  vibração.

Referências:
An  ISE  Tutorial  -­‐  Luiz  Rennó
Projeto  Debouncer  -­‐  Camila  Simões  da  Costa  Cunha  Vasconcellos,  Henrique  
Duarte  Faria,  Patrick  Svaiter,  Paulo  Roberto  Yamasaki  Catunda
Relatório  de  Sistemas  Digitais:  Projeto  Base  de  Tempo  -­‐  Michael  D.  Barreto  e  
Silva,  Luiz  Carlos,  Gabriela  Dantas

29

Você também pode gostar