tutorial)*)xilinx)ise - del.ufrj.brmario.filho/tutorial.pdf · 4.)vhdl)básico ’...

Post on 26-Jan-2019

259 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Tutorial  -­‐  Xilinx  ISE

Universidade  Federal  do  Rio  de  JaneiroEscola  Politécnica

Departamento  de  Eletrônica  e  Computação

         Autores:                 Orientador:Artur  Lemos               Mário  VazIoav  LichtensteinThiago  Lobo

Índice:1.  Introdução                   32.  Instalação                     43.  Criando  um  novo  projeto             54. VHDL  Básico                   85. Simulando  um  projeto               156.  Criando  um  DCM                 237.  Implementando  um  projeto  na  FPGA                      268.  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  IEEE2. library  IEEE;3. use  IEEE.std_logic_1164.all;4.  5. -­‐-­‐  essa  é  a  entidade  (entity)6. entity  ANDGATE  is7.    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  is15. begin16.    O  <=  I1  and  I2;17. end  architecture  behavioral;

  Como  podemos  ver,  a  leitura  do  bloco  “entity”  permite  imaginarmos  o  seguinte:  

 

  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.

I1

9

I1

I2O

ANDGATE

  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  is23.      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  is30. signal  cnt,  cnt1  :  integer  :=  0;31. signal  div_temp,  div_temp2  :  std_logic  :=  '0';32.  33. begin34. div  <=  div_temp;35. div2  <=  div_temp2;36. process  (clk_in)  begin37.                if  (clk_in'event  and  clk_in  =  '1')  then38.                                if  cnt  >=  n  then39.                                                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')  then47.                                if  cnt1  >=  n  then48.                                                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  is66.      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  is80. component  clk_div81.    port  (clk_in    :  in    std_logic;  82.                div          :  out  std_logic;83.                div2        :  out  std_logic);84. end  component;85.  86. COMPONENT  dcm187. 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.begin101.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  IS122.END  debouncer2_tb;123.  124.ARCHITECTURE  behavior  OF  debouncer2_tb  IS  125.  126.        COMPONENT  debouncer2127.        PORT(128.                  Clk  :  IN    std_logic;129.                  Key  :  IN    std_logic;130.                  pulse  :  OUT    std_logic131.                );132.        END  COMPONENT;133.        134.  135.      -­‐-­‐Inputs136.      signal  Clk  :  std_logic  :=  '0';137.      signal  Key  :  std_logic  :=  '0';138.  139.      -­‐-­‐Outputs140.      signal  pulse  :  std_logic;141.  142.      -­‐-­‐  Clock  period  definitions143.      constant  Clk_period  :  time  :=  10  ms;144.  145.BEGIN146.  147.                -­‐-­‐  Instantiate  the  Unit  Under  Test  (UUT)148.      uut:  debouncer2  PORT  MAP  (149.                    Clk  =>  Clk,

20

150.                    Key  =>  Key,151.                    pulse  =>  pulse152.                );153.  154.      -­‐-­‐  Clock  process  definitions155.      Clk_process  :process156.      begin157.                                Clk  <=  '0';158.                                wait  for  Clk_period/2;159.                                Clk  <=  '1';160.                                wait  for  Clk_period/2;161.      end  process;162.  163.  164.      -­‐-­‐  Stimulus  process165.      stim_proc:  process166.      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ódigoDebouncer:

180.LIBRARY  ieee;181.USE  ieee.STD_LOGIC_1164.all;182.USE  ieee.STD_LOGIC_UNSIGNED.all;183.  184.ENTITY  debouncer2  IS185.                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  IS191.SIGNAL  SHIFT_KEY  :  STD_LOGIC_VECTOR(3  DOWNTO  0)  :=  "1111";192.  193.BEGIN194.PROCESS195.        BEGIN196.                            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  CatundaRelatório  de  Sistemas  Digitais:  Projeto  Base  de  Tempo  -­‐  Michael  D.  Barreto  e  Silva,  Luiz  Carlos,  Gabriela  Dantas

29

top related