Post on 17-Apr-2015
VHDLVery High Speed Integrated Circuit
Hardware Description Language
Prof. Eduardo Todt
2008
Introdução
• Linguagem para descrição de sistemas digitais• Evoluiu para simulação, análise, síntese• Origem: meados década de 80, US Department of
Defense e IEEE• Norma IEEE 1076-1993, 2000, 2002• Outras linguagens: VERILOG, SystemC, ABEL
– VHDL predomina na Europa, VERILOG E.U.A.
Níveis de abstração
Moraes & Calazans 2006
Estrutura de uma descrição VHDL
VHDL entity
Interface(entity declaration)
Body(architecture)
sequential, combinational,
Processes,subprograms
portsentity NAME_OF_ENTITY is
[generic generic_declarations);]
port (signal_names: mode type;
signal_names: mode type;
:
signal_names: mode type);
end [NAME_OF_ENTITY] ;
-- exemplo de entityentity alarme is port ( porta, identificado: in std_logic;
sirene: out std_logic);end alarme;
Entity
Entity define interfaces e o nome de um objeto
entity NAME_OF_ENTITY is
[generic generic_declarations);]
port (signal_names: mode type;
signal_names: mode type;
:
signal_names: mode type);
end [NAME_OF_ENTITY] ;
port: interfacesmode: in | out | buffer | inouttype: bit | bit_vector | std_logic | std_logic_vector |
boolean | integer | real | character | time | ...
• std_logic tem 9 valores (U,Z,X,0,1,W,L,H,-) definidos em std_logic_1164 package• bit tem valores 0 ou 1
Declaração generic
generic (
constant_name: type [:=value] ;
constant_name: type [:=value] ;
:
constant_name: type [:=value] );
Define constantes locais, em geral para tempo (delay de portas) e tamanho de barramentos e registradores
ArchitectureArchitecture especifica operação e implementação
* uma entidade pode ter várias arquiteturas associadas
architecture architecture_name of NAME_OF_ENTITY is-- Declarations
-- components declarations-- signal declarations-- constant declarations-- function declarations-- procedure declarations-- type declarations
:
begin-- Statements
:
end architecture_name;
Modelo comportamental architecture behavioral of alarme isbegin sirene <= (porta and not identificado);
end behavioral;
----------------------------------------------------------------
entity XNOR2 isport (A, B: in std_logic;
Z: out std_logic);end XNOR2;
architecture behavioral_xnor of XNOR2 issignal X, Y: std_logic;begin X <= A and B; Y <= (not A) and (not B); \ 3 comandos concorrentes Z <= X or Y; / End behavioral_xnor;
Modelo estrutural
architecture structural of alarme is
-- declarações de tipos de componentes utilizados
component AND2 port (in1, in2: in std_logic;
out1: out std_logic); end component;
component NOT1 port (in1: in std_logic;
out1: out std_logic); end component;
-- declaração de sinal para interconexão
signal n_identificado: std_logic;
begin
-- instanciação dos componentes utilizados e sinais de ligação
U0: NOT1 port map (identificado, n_identificado);
U1: AND2 port map (porta, n_identificado, sirene);
end structural;
Associação posicional x explícita
• posicional
component AND2 port (in1, in2: in std_logic;
out1: out std_logic); end component;
U1: AND2 port map (porta, n_identificado, sirene);
• explícita
component AND2 port (in1, in2: in std_logic;
out1: out std_logic); end component;
U1: AND2 port map (in1 => porta, in2=> n_identificado,
out1=> sirene);
Library
library ieee; use ieee.std_logic_1164.all; -- tipos padrãouse ieee.std_logic_arith.all; -- funções aritméticas, conversão de tipos e
comparações para signed, unsigned, integer, std_ulogic, std_logic and std_logic_vector
use ieee.std_logic_unsigned.all; -- idem para unsigneduse ieee.std_logic_signed.all; -- idem para signed use ieee. std_logic_misc. all; -- tipos e constantes adicionais
overload de operadores, como “+” permite operações com vetores de bits
all indica que são utilizados todos elementos, poderia ser especificado algum
Package
• encapsulam declarações para serem compartilhadas
• podem ter declarações e opcionalmente um corpo
-- Package declarationpackage name_of_package is
package declarationsend package name_of_package;
-- Package body declarationspackage body name_of_package is
package body declarationsend package body name_of_package;
Package
package data_types issubtype address is bit_vector(24 downto 0);subtype data is bit_vector(15 downto 0);constant vector_table_loc : address;function data_to_int(value : data) return integer;function int_to_data(value : integer) return data;
end data_types;
package body data_types is
constant vector_table_loc : address := X"FFFF00";
function data_to_int(value : data) return integer isbody of data_to_int
end data_to_int;
function int_to_data(value : integer) return data isbody of int_to_data
end int_to_data;
end data_types;
Detalhes de implementaçãoomitidos, corpo necessário
Moraes & Calazans 2006
Package
library ieee, my_func;use ieee.std_logic_1164.all;use my_func.basic_func.all; my_func é a biblioteca criada (.vhdl) basic_func é o nome de um conjunto declaração e
corpo definidos biblioteca do usuário (default): work – contém
todos objetos definidos no projeto
Elementos de VHDL
• identificadores– caracteres A-Z, a-z, 0-9 e underscore
– case insensitive
– extended identifiers: com ´\´, case sensitive, admitem caracteres especiais. Ex: \input #1\, \BUS:\data\
• keywords: abs, all, and, assert, begin, not, case, if, mod, not, or, out, select, then, use, when, xor, ...
Elementos de VHDL
• números– integer literals: 12, 256E3, 12E+6– real literals: 1.2, 256.24, 3.14E-2– base 2: 2#1010#– base 16: 16#1a#– undescores são ignorados:
2#1010_1100_0011#– fortemente tipado: integer 1, real 1, bit 1 são
diferentes
Elementos de VHDL
• caracteres, strings, strings de bits– caractere: ‘A’– string de caracteres: “abracadabra”– bit strings
• b”10110010”
• x”1ff0”
Elementos de VHDL• constantes
constant list_of_name_of_constant: type [ := initial value] ;constant DELAY: time := 5 ns;constant DATA_BUS: integer:= 32;
• sinais– declarados fora de processos– signal list_of_signal_names: type [ := initial value] ;
signal clock: std_logic;
– sinais são atribuídos após um delay:SUM <= (A xor B) after 2 ns;entrada <= ‘0’, ‘1’ after 2ns, ‘0’ after 10ns, ‘1’ after 15 ns;
– são atualizados no final de processos ou em wait
• variáveis– são atualizadas imediatamente– devem ser declaradas dentro de processos– variable list_of_variable_names: type [ := initial value] ;
variable CTL_BIT: bit :=0;– atribuição: Variable_name := expression;
soma:= 120;
Signals x Variables
architecture var of teste is signal trigger, soma: integer := 0; begin
processvariable var1: integer :=1;variable var2: integer :=2;variable var3: integer :=3;
beginwait on trigger;var1 := var2;var2 := var1 + var3;var3 := var2;soma <= var1 + var2 + var3;
end process;end var;
Signals x Variables
architecture sig of teste is signal trigger, soma: integer := 0; signal sig1: integer :=1;
signal sig2: integer :=2;signal sig3: integer :=3;
beginprocessbegin
wait on trigger;sig1 <= sig2;sig2 <= sig1 + sig3;sig3 <= sig2;soma <= sig1 + sig2 + sig3;
end process;end sig;
Signals x Variables
• no exemplo com variáveis a avaliação é seqüencial, resultando em 12
• no exemplo com sinais, a avaliação é concorrente resultando em 6
• todos sinais são atualizados delta time depois do sinal trigger, ao final de processos
Mais sobre sinais e variáveis
• podem ser especificados intervalo e valor inicial– variable alunos: integer range 1 to 60 := 1;– signal alunos: integer range 1 to 60 := 1;– signal flag: std_logic := ‘0’;
• sinais em geral são para comunicação entre módulos
• sinais podem ser declarados em entity, architecture ou package
• sinais não podem ser declarados em processos, mas podem ser inicializados nestes
• signal byte: std_logic_vector (7 downto 0);byte <= (7 => ‘1’, 5 downto 2 => ‘1’, others => ‘0’);
Tipos de dados
• bit: ‘0’ ou ‘1’• bit_vector: “0011”, x”1f00”, ...• boolean: true ou false• real• integer• character: ‘a’, ‘0’, ou string “abcd”• physical: ms, ps, mV, sec, min, ...• intervalos:
– integer range 1 to 10– integer range 10 downto 1– sem range significa todos valores possíveis– <> significa declaração postergada do intervalo
• enumerações– type estados is (“idle”, “running”, “halt”);– type octal is (‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’); – type oper is (load, store, add, sub);
Arrays
• coleção de elementos de mesmo tipo– type array_name is array (indexing scheme) of element_type;
• type WORD1 is array (15 downto 0) of std_logic;
• type WORD2 is array (0 to 15) of std_logic;
• type FRAME1 is array (0 to 7) of integer;
• type MEMORY is array (address) of WORD1;
– preenchimento de array:
type a is array (1 to 4) of character;
posicional: (‘l', ‘e', ‘s', ‘s')
por nome: (1 => ‘l', 3 => ‘s', 2 => ‘e' , 4 => ‘s')
valores default: (‘l', ‘e', others => ‘s’)
Arrays multidimensionais
type MATRIX3X2 is array (1 to 3, 1 to 2) of integer;
variable DATA_ARRAY: MATRIX3X2 := ((1,2), (2,3), (4,6));
1 2
2 3
4 6
Records• coleção de elementos que podem ser de tipos distintos
type name isrecord
identifier :subtype_indication;:
identifier :subtype_indication;end record;
type FRAME isrecord
flag : boolean;source : bit_vector(7 downto 0);dest : bit_vector(7 downto 0);data : bit_vector (31 downto 0);
end record; signal A, B: FRAME;A.dest = “1100_0011”;
Tipo padrão std_ulogic
• tipo não resolvido (indefinido em caso de conflitos)• 9 valores• std_logic_1164 package
type STD_ULOGIC is (‘U’, -- uninitialized‘X’, -- forcing unknown‘0’, -- forcing 0‘1’, -- forcing 1‘Z’, -- high impedance‘W’, -- weak unknown‘L’, -- weak 0‘H’. -- weak 1‘-‘); -- don’t care
Tipo padrão std_logic
• tipo resolvido• tipo mais comumente utilizado em descrições de hardware• std_logic_1164 package
SUBTYPE std_logic IS resolved std_ulogic; TYPE std_logic_vector IS ARRAY ( NATURAL RANGE <>) OF std_logic; -------------------------------------------------------------------
-- resolution function -------------------------------------------------------------------
CONSTANT resolution_table : stdlogic_table := ( -- --------------------------------------------------------- -- | U X 0 1 Z W L H - | | -- --------------------------------------------------------- ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | ( 'U', 'X', '0', 'X', '0', '0', '0', '0', 'X' ), -- | 0 | ( 'U', 'X', 'X', '1', '1', '1', '1', '1', 'X' ), -- | 1 | ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X' ), -- | Z | ( 'U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X' ), -- | W | ( 'U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X' ), -- | L | ( 'U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X' ), -- | H | ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - | );
Conversões de tipos
std_logic_1164 package
std_ulogic to bit to_bit(expression)
std_logic_vector to bit_vector to_bitvector(expression)
std_ulogic_vector to bit_vector to_bitvector(expression)
bit to std_ulogic To_StdULogic(expression)
bit_vector to std_logic_vector To_StdLogicVector(expression)
bit_vector to std_ulogic_vector To_StdUlogicVector(expression)
std_ulogic to std_logic_vector To_StdLogicVector(expression)
std_logic to std_ulogic_vector To_StdUlogicVector(expression)
• IEEE std_logic_unsigned e std_logic_arith possuem conversão entre inteiros e std_logic_vector e vice-e-versa, além de overload de operadores. Com isto pode-se realizar operações aritméticas com vetores de bits.
Atributos de sinais
• signal_name’event– if (CLOCK’event and CLOCK=’1’) then …
• scalar_type’low
• scalar_type’high
• scalar_type’left
• scalar_type’right
• ...
Operadores
Van der Spiegel, 2006
Ordem de precedência: classe 7 (maior) para classe 1 (menor)Operadores de mesma classe: esquerda para direita na expressãoParêntesis para alterar ordem
Comandos seqüenciais• comandos seqüenciais são utilizados em processos, funções e
procedimentos• um processo é um comando concorrente, mas os comandos dentro do
mesmo são executados seqüencialmente
[process_label:] process [ (sensitivity_list) ] [is][ process_declarations]
beginlist of sequential statements such as:
signal assignmentsvariable assignmentscase statementexit statementif statementloop statementnext statementnull statementprocedure call wait statement
end process [process_label];
Comandos seqüenciais• atribuições de variáveis são restritas ao escopo dos
processos e são seqüenciais
• alteração em um sinal na sensitivity list ocasiona execução imediata do processo
• se não há sensitivity list é necessário incluir um wait para que o processo interrompa
• não é possível ter juntos sensitivity list e wait no mesmo processo
• variáveis são declaradas no processo antes do begin
Exemplo de processo: FF D
library ieee;use ieee.std_logic_1164.all;
entity FlipFlopD isport (clk, clear, D: in std_logic; Q: out std_logic);end FlipFlopD; architecture comportamental of FlipFlopD isbegin process (clk, clear)
beginif (clear = ‘1’) then
Q <= ‘0’;elsif (clk’event and clk = ‘1’) then
Q <= D;end if;
end process;end comportamental;
Testbench para FF D
entity FFD_tb isend; architecture teste of FFD_tb issignal D_tb, clear_tb, Q_tb: std_logic;signal clock_tb: std_logic:='0';component FlipFlopD is
port(clk, clear, D: in std_logic; Q: out std_logic);end component;
beginF1: FlipFlopD port map(clock_tb,clear_tb,D_tb, Q_tb);D_tb <= '0', '1' after 50 ns, '0' after 100 ns; clock_tb <= not clock_tb after 25 ns;clear_tb <= '1', '0' after 60 ns;
end;
Comando if
if condition thensequential statements
[elsif condition thensequential statements ]
[else sequential statements ]
end if;
if S1=’0’ and S0=’0’ thenZ <= A;
elsif S1=’0’ and S0=’1’ thenZ <= B;
elsif S1=’1’ and S0=’0’ thenZ <= C;
elsif S1=’1’ and S0=’1’ thenZ <= D;
end if;
Comando case
case expression iswhen choices =>
sequential statementswhen choices =>
sequential statements-- branches are allowed
[ when others => sequential statements ]end case;
choices ::= choice { | choice }choice ::=
simple_expression| discrete_range| element_simple_name| others
Comando caseentity MUX_4_1 is port ( SEL: in std_logic_vector(2 downto 1);
A, B, C, D: in std_logic;Z: out std_logic);
end MUX_4_1;architecture behav_MUX41 of MUX_4_1 isbegin PR_MUX: process (SEL, A, B, C, D) begin
case SEL iswhen “00” => Z <= A; when “01” => Z <= B; when “10” => Z <= C; when “11” => Z <= D;when others => Z <= ‘X’;
end case; end process PR_MUX;end behav_MUX41
Comando case
case element_colour iswhen red => -- escolha simples
statements for red;when green | blue => -- ou
statements for green or blue;when orange to turquoise => -- intervalo
statements for these colours;end case;
case opcode iswhen X"00" => perform_add;when X"01" => perform_subtract;when others => signal_illegal_opcode;
end caseMoraes & Calazans 2006
basic loop
[ loop_label :] loop
sequential statements
[next [label] [when condition];
[exit [label] [when condition];
end loop [ loop_label];
basic loop
entity COUNT31 is port ( CLK: in std_logic;
COUNT: out integer); end COUNT31;architecture behav_COUNT of COUNT31 isbegin P_COUNT: process
variable intern_value: integer :=0; begin
COUNT <= intern_value;loop wait until CLK=’1’;
intern_value:=(intern_value + 1) mod 32; COUNT <= intern_value;end loop;
end process P_COUNT;end behav_COUNT;
while loop
[ loop_label :] while condition loop
sequential statements
[next [label] [when condition];
[exit [label] [when condition];
end loop[ loop_label ];
while index < length and str(index) /= ' ' loop
index := index + 1;end loop;
Comandos de loop
[ loop_label :]iteration_scheme loop
sequential statements
[next [label] [when condition];
[exit [label] [when condition];
end loop [loop_label];
• next termina a iteração corrente
• exit encerra o loop
for loop
[ loop_label :] for identifier in range loopsequential statements[next [label] [when condition];[exit [label] [when condition];
end loop[ loop_label ];
• identifier é declarado pelo próprio loop e é válido somente no escopo
do loop; seu valor não pode ser atribuído dentro do loop• range:
integer_expression to integer_expression integer_expression downto integer_expression
Exemplo com for loop
function conv (byte : word8) return integer isvariable result : integer := 0;variable k : integer := 1;
beginfor index in 0 to 7 loop
if ( std_logic(byte(index))='1') then result := result + k;
end if;
k := k * 2; end loop; return result;
end conv ;
Moraes & Calazans 2006
Comando wait
• pára um processo até que um evento ocorra
wait until condition; -- algums sistemas só suportam estewait for time expression;wait on signal;wait;
wait until signal = value;wait until signal’event and signal = value;wait until CLK’event and CLK=’1’; -- \ sãowait until CLK=’1’; -- / idênticos!
** comportamento do if CLK=´1´ é distinto ....
Comando null
• fazer nada• útil em case statement
case controller_command is
when forward =>
engage_motor_forward;
when reverse => engage_motor_reverse;
when idle => null;
end case;
Funções
• Funções executam comandos seqüenciais e retornam um valor como o valor da função. Funções não alteram seus parâmetros formais.
function identifier [ ( formal parameter list ) ] return return_type ;
function random return float ; function is_even (N: integer) return boolean ;
• parâmetros separados por “;”
Estruturas concorrentes
• atribuição de sinaisA <= B + C;
E <= B + D;
• atribuição de sinais com escolhaTarget_signal <= expression when Boolean_condition else
expression when Boolean_condition else
:
expression;
Estruturas concorrentes
• atribuição de sinais com seleção
with choice_expression select
target_name <= expression when choices,
target_name <= expression when choices,
:
target_name <= expression when choices;
Estruturas concorrentes
• A escolha pode ser mais de um valor ou um range:
target <= value1 when “000”,
value2 when “001” | “011” | “101” ,
value3 when others;
Funções
function identifier [ ( formal parameter list ) ] return return_type is
[declarations] begin
sequential statement(s) return some_value;
end function identifier;
function raiz_quadrada(N: float) return float is variable aux: float; begin
-- cálculo da raiz quadradareturn aux;
end function raiz_quadrada;
Procedimentos
• Procedimentos executam comandos seqüenciais e retornam valores em objetos globais ou por meio dos parâmetros formais
• Quando colocados em um package, a declaração fica na parte de declaração do package e a implementação no body do package
Procedimentos
procedure identifier [ ( formal parameter list ) ] ;
procedure open_door ;procedure build ( A : in integer;
B : inout signal bit_vector;
C : out real; D : file ) ;
Procedimentos
procedure identifier [ ( formal parameter list ) ] is
[declarations] begin sequential statement(s) end procedure identifier ;
library IEEE; use IEEE.Std_Logic_1164.all; package calcHP is subtype ... type ... constant ... procedure somaAB ( signal A,B: in regsize; signal S: out regsize); end calcHP; package body calcHP is procedure somaAB ( signal A,B: in regsize; signal S: out regsize); is variable carry : STD_LOGIC; begin .... end procedure somaAB; end package body calcHP; library IEEE; use IEEE.Std_Logic_1164.all; use work.calcHP.all; entity calculadora is port( clock : in bit; saida : out regsize; flag : out std_logic); end; architecture rtl of calculadora is begin
... somaAB( opA, opB, cin, soma, cout); ... end rtl;
A procedure é declarada no package
A procedure é implementada no package body
A procedure é utilizada na architecture
Significa: utilizar todas as declarações do package calcHP
Moraes & Calazans 2006
Codificador 7 segmentoswith showb select
DISPB <="0000001" when "0000","1001111" when "0001","0010010" when "0010","0000110" when "0011","1001100" when "0100","0100100" when "0101","0100000" when "0110","0001111" when "0111","0000000" when "1000","0001100" when "1001","0001000" when "1010","1100000" when "1011","0110001" when "1100","1000010" when "1101","0110000" when "1110","0111000" when "1111";
bg
a
ce
f
d
– Em um codificador a saída é uma função combinacional da entrada.
– O comando ‘with’ é utilizado para atribuir um dado valor a um sinal, em função de um sinal de controle.
Relacione o estado dos 7 segmentos ´DISPB´ com o estado do número binário ´showb´
Moraes & Calazans 2006
Codificador com prioridade
Em um codificador com prioridade se o bit menos significativo for ‘1’ a saída é ´0´, se o bit seguinte for 1, independentemente do anterior, a saída é ´1´; e assim sucessivamente.
Exemplo ( s(3) tem maior prioridade ) :
Y <= ”11" when s(3) = ‘1’ else
“10” when s(2) = ‘1’ else“01” when s(1) = ‘1’ else
“00”;
Importante haver condição default em atribuições e estruturas similares:NÃO HAVENDO ESTA CONDIÇÃO IMPLICA EM HAVER MEMORIZAÇÃO DO SINAL - diferente de software! (warning latch inferred)
Moraes & Calazans 2006
Decodificador
– decodificador é utilizado basicamente para acionar uma saída em função de um
determinado endereço
– Mesma construção que o codificador
– Exemplo para um decodificador 38
with endereço select saída <= "00000001" when "000",
"00000010" when "001","00000100" when "010","00001000" when "011","00010000" when "100","00100000" when "101","01000000" when "110","10000000" when "111";
Moraes & Calazans 2006
MUX 2x1
entity MUX_2x1 is port (sel, A, B: in std_logic; Z: out std_logic);end MUX_2x1;
architecture comport of MUX_2x1 isbegin P1: process (sel, A, B) begin
if (not sel) thenZ <= A;
elseZ <= B;
end if; end process P1;end comport;
MUX 4x1entity MUX_4x1 is port(sel: in std_logic_vector(1 downto 0);
A, B, C, D: in std_logic; Z: out std_logic);
end MUX_4x1;
architecture comport of MUX_4x1 isbegin process (sel, A, B, C, D) begin
case sel iswhen “00” => Z <= A; when “01” => Z <= B; when “10” => Z <= C; when “11” => Z <= D;when others => Z <= ‘X’;
end case; end process;end comport;
MUX 2x1 concorrente
entity MUX_2x1 is
port (sel, A, B: in std_logic; Z: out std_logic);
end MUX_2x1;
architecture comport of MUX_2x1 is
begin
Z <= A when sel=’0’ else
B;
end comport;
MUX 2x1 concorrente
entity MUX_2x1 is port (sel, A, B: in std_logic; Z: out std_logic);end MUX_2x1;
architecture comport of MUX_2x1 isbegin
with sel select Z <= A when “0”, B when “1”;
end comport;
• todos casos devem ser cobertos, pode ser usado others
Mais um mux
Saida <= In0 when 0 | 1,
In1 when 2 to 5,In2 when 6,
In3 when 7,
'Z' when others;
ULA (1)
outalu_int <= opB when op_alu=st else
opA when op_alu=mov else
opA and opB when op_alu=and_i else
opA or opB when op_alu=or_i else
opA xor opB when op_alu=xor_i else
opB(15 downto 8) & opA(7 downto 0) when op_alu=ldli else
opA - opB when op_alu=sub else
not opA when op_alu=not_i else
opA(14 downto 0) & '0' when op_alu=sl else
'0' & opA(15 downto 1) when op_alu=sr else
opB + apA;
Moraes & Calazans 2006
ULA (2)
process(M,cin,OPCODE,OPERA,OPERB)begin
if (M='1') then -- modo 1 é lógico case OPCODE is
when "0000" => saida <= not(OPERA);when "0001" => saida <= not(OPERA and OPERB);when "0010" => saida <= (not(OPERA)) or OPERB;when "0011" => saida <= "0001";........ continuam as outras operações
end case;
else -- modo 0 é aritmético case OPCODE is
when "0000" => tempA <= OPERA; tempB <= OPERB;
when "0001" => tempA <= not OPERA; tempB <= OPERB;when "0010" => tempA <= OPERA; tempB <= "1111";........ continuam as outras operações
end case;
SUM(tempA, tempB, cin, saida, C4);
end if;
end process;Moraes & Calazans 2006
Registrador
– registradores são basicamente sinais declarados em processos com sinal de sincronismo (exemplo: clock). Para efeito de síntese e simulação, é aconselhável introduzir um reset assíncrono.
process (clock, reset)begin
if reset = '1' thenreg <= (others =>’0’); -- portável;
elsif clock 'event and clock='1' thenreg <= barramento_A;
end if; end process;
1) Como introduzir um sinal de “enable” no registrador, para habilitar a escrita?
2) Como implementar um registrador “tri-state” controlado por um sinal “hab”?
Moraes & Calazans 2006
– Registrador com largura de palavra parametrizável, com ‘ce’:library ....
entity regnbit is generic(N : integer := 16); port( ck, rst, ce : in std_logic; D : in STD_LOGIC_VECTOR (N-1 downto 0); Q : out STD_LOGIC_VECTOR (N-1 downto 0) );end regnbit;
architecture regn of regnbit is begin
process(ck, rst) begin if rst = '1' then Q <= (others => '0'); elsif ck'event and ck = '0' then if ce = '1' then Q <= D; end if; end if; end process; end regn;
Registrador
genericdefine um parâmetro do módulo
Uso:rx: regnbit generic map(8) port map(ck => ck, rst => rst, ce => wen, D => RD, Q => reg);
Moraes & Calazans 2006
process (clock, reset)begin
if reset = '1' thenA <= 0; B <= 0; C <= 0;
elsif clock'event and clock='1' thenA <= entrada;B <= A;C <= B;
end if; end process;
1) Desenhe o circuito acima utilizando flip-flops2) A ordem das atribuições (A,B,C) é importante ? O que
ocorreria se fosse uma linguagem de programação tipo C?
Registrador de deslocamento
Moraes & Calazans 2006
– Atribuição dentro/fora de process:process (clock, reset)
beginif clock'event and clock='1' then
A <= entrada;B <= A;C <= B; Y <= B and not (C); -- dentro do process
end if; end process;
X <= B and not (C); -- fora do process
Qual a diferença de comportamento nas atribuições à X e a Y?
– Conclusão: - sinais atribuídos em processos, com controle de clock, serão
sintetizados com flip-flops.- Sinais fora de processos ou em processos sem variável de sincronismo
(clock) serão sintetizados com lógica combinacional.
Registrador
Moraes & Calazans 2006
Contador
entity contup isport ( clock, reset, Load, Enable: In std_logic;
DATABUS : In Std_logic_Vector (5 downto 0);Upcount2 : Out Std_logic_Vector (5 downto 0));
end contup;
architecture RTL of contup isSignal Upcount : std_logic_Vector (5 downto 0);
beginUpcount2 <= Upcount;
Upcounter : Process (clock, reset)begin
if reset = '1' thenUpcount <= "000000";
elsif clock'event and clock='1' then if ENABLE = '1' then if LOAD = '1' then Upcount <= DATABUS;
else Upcount <= Upcount + 1; end if; end if; end if;
end process Upcounter;end RTL; Moraes & Calazans 2006
ROM
package ROM is -- definição de uma rom 12x4
constant largura : integer := 4;
subtype palavra is std_logic_vector(1 to largura);
subtype tamanho is integer range 0 to 11;
type mem_rom is array (0 to 11) of palavra;
constant ROM1 : mem_rom :=
"1100", "1100","0100","0000", "0110","0101","0111",
"1100","0100","0000","0110","0101");
end ROM;
Moraes & Calazans 2006
ROMuse work.ROM.all;
entity contador is port( clock, reset : in bit; waves : out palavra);
end;
architecture A of contador issignal step : tamanho := 0;
beginwaves <= ROM1(step); -- conteúdo da ROM na saídaprocess begin
wait until clock'event and clock='1';if reset='1' then
step <= 0; -- primeiro estado
elsif step = tamanho'high thenstep <= tamanho'high; -- tranca !
elsestep <= step + 1; -- avança 1
passoend if;
end process;end A; Moraes & Calazans 2006
Máquina de estadosentity MOORE is port(entrada1, clock : in std_logic; saida1: out std_logic); end;
architecture comportamental of MOORE is type STATES is (S0, S1, S2, S3); -- tipo enumerado signal EA, PE : STATES; begin
controle: process(clock, reset) begin if reset=‘1’ then EA <= S0;
elsif clock'event and clock='1’ then EA <= PE; end if;
end process;
combinacional: process(EA, entrada1) begin case EA is
when S0 => saida1 <= '0'; if entrada1='0' then PE<=S0; else PE<=S2; end if;
when S1 => saida1 <= '1'; if entrada1='0' then PE<=S0; else PE<=S2; end if;
when S2 => saida1 <= '1'; if entrada1='0' then PE<=S2; else PE<=S3; end if;
when S3 => saida1 <= '0'; if entrada1='0' then PE<=S3; else PE<=S1; end if;
end case; end process;
end comportamental;
Processador Cleopatra
• Material a seguir cedido pelos autores Calazans e Moraes.
Arquitetura CLEÓPATRA v3.0
Arquitetura CLEÓPATRA
ce
rw
entity control is
port ( reset, ck, n, z, c, v : in std_logic;halt : out std_logic;ir : in regsize;
uins : out microinstrucao )end control;
entity datapath isport( ck, reset : in
std_logic;address, ir :
out regsize;datamem :
inout regsize;uins : in
microinstrucao; n, z, c, v : out
std_logic ); end datapath;
DATAMEM
ADDRESSMEMÓRIAdados e programa
CPU
ck
reset
halt
MICROINSTRUÇÃO => PALAVRA DE CONTROLE
MAR
MDR
IR
RS
PC
AC
ULA
BUS_B BUS_A0 mux1 sel
escreve na memória
lê da memória
ADDRESS
DATAMEM
Codificação de escrita
Codificação de leitura
w
r
ulnz
lcv
CERW
CE RW
type microinstrucao is record w,r,u: opcode; ce, rw, lnz, lcv : std_logic;end record;
NZCV
Barramento de dados v3.0
FETCH 1/3
MAR (0)
MDR (1)
IR (2)
RS (5)
PC(3)
AC (4)
ULA
0 mux1 sel
escreve na memória
lê da memória
DATAMEM
Codificação de escrita
Codificação de leitura
w
r
ulnz
lcv
CERW
CE RW
NZCV
MAR PCuins <= ( 0, 3, 7, '0', '0', '0', '0');
type microinstrucao is record w,r,u: opcode; ce, rw, lnz, lcv : std_logic; end record;
FETCH 2/3
MAR (0)
MDR (1)
IR (2)
RS (5)
PC(3)
AC (4)
ULA
0 mux1 sel
escreve na memória
lê da memória
DATAMEM
Codificação de escrita
Codificação de leitura
w
r
ulnz
lcv
CERW
CE RW
MDR PMEM(MAR); PC++uins <= ( 1, 3, 1, '1', '1', '0', '0');
type microinstrucao is record w,r,u: opcode; ce, rw, lnz, lcv : std_logic; end record;
NZCV
FETCH 3/3
MAR (0)
MDR (1)
IR (2)
RS (5)
PC(3)
AC (4)
ULA
0 mux1 sel
escreve na memória
lê da memória
DATAMEM
Codificação de escrita
Codificação de leitura
w
r
ulnz
lcv
CERW
CE RW
IR MDRuins <= ( 2, 1, 4, '0', '0', '0', '0');
type microinstrucao is record w,r,u: opcode; ce, rw, lnz, lcv : std_logic; end record;
NZCV
BLOCO DE DADOS - COMPONENTES (7)
MAR
MDR
IR
RS
PC
AC
ULA
BUS_B BUS_A0 mux1 sel
escreve na memória
lê da memória
ADDRESS
DATAMEM
Codificação de escrita
Codificação de leitura
w
r
ulnz
lcv
CERW
CE RW
NZCV
BD - ACESSO À MEMÓRIA
-- dados provenientes ou da memória ou da ULA sel1 <= uins.ce and uins.rw;outmux <= out_ula when sel1='0' else datamem; -- escrita para a memóriasel2 <= uins.ce and (not uins.rw);datamem <= out_ula when sel2='1' else
"ZZZZZZZZ";
0 mux1 sel
escreve na memória
lê da memória
CERW
CE RW
out_ula
datamem
BD - REGISTRADORES
ir <= reg_ir; -- instrução corrente, a ser utilizada no bloco de controle
R1: reg8clear port map
( clock=>ck, reset=>reset, ce=>wmar, D=>out_ula, Q=>address);
R2: reg8clear port map
( clock=>ck, reset=>reset, ce=>wmdr, D=>outmux, Q=>mdr);
R3: reg8clear port map
( clock=>ck, reset=>reset, ce=>wir, D=>out_ula, Q=>reg_ir);
R4: reg8clear port map
( clock=>ck, reset=>reset, ce=>wpc, D=>out_ula, Q=>pc);
R5: reg8clear port map
( clock=>ck, reset=>reset, ce=>wac, D=>out_ula, Q=>ac);
R6: reg8clear port map
( clock=>ck, reset=>reset, ce=>wrs, D=>out_ula, Q=>rs);
BD - ACESSO AOS BARRAMENTOS
busB <= mdr when rmdr='1' else "ZZZZZZZZ";
busB <= reg_ir when rir='1' else "ZZZZZZZZ";
busA <= pc when rpc='1' else "ZZZZZZZZ";
busA <= ac when rac='1' else "ZZZZZZZZ";
busA <= rs when rrs='1' else "ZZZZZZZZ";
MDR
IR
RS
PC
AC
ULA
BUS_B BUS_A
Uso de tri-states:
BD - CODIFICAÇÃO DE ESCRITA
wmar <= '1' when uins.w=0 else '0';
wmdr <= '1' when uins.w=1 or uins.w=6 else '0';
wir <= '1’ when uins.w=2 else '0';
wpc <= '1' when uins.w=3 or uins.w=6 else '0';
wac <= '1' when uins.w=4 else '0';
wrs <= '1' when uins.w=5 else '0';
BD - CODIFICAÇÃO DE LEITURA
rmdr <= '1' when uins.r =1 or uins.r=6 or uins.r=7 else '0';
rir <= '1' when uins.r =2 else '0';
rpc <= '1' when uins.r =3 or uins.r=7 else '0';
rac <= '1' when uins.r =4 or uins.r=6 else '0';
rrs <= '1' when uins.r=5 else '0';
BD - ULAum <= "00000001";zero <= '0';process(uins.u,busA,busB) begin case uins.u is
when 0 => somaAB( busA, busB, zero, out_ula, cout);when 1 => somaAB( busA, um, zero, out_ula, cout);when 2 => out_ula <= not busA;when 4 => out_ula <= busB;when 5 => out_ula <= busA or busB;when 6 => out_ula <= busA and busB;when 7 => out_ula <= busA;when others => null;
end case;end process;
BD - FLAGS DE ESTADO (falta v)
Chamada de FUNÇÃO
process(ck,reset,uins) begin if (reset='1') then c <= '0'; n <= '0'; z <= '0'; elsif ck'event and ck='0’ then
if uins.c='1' then c <= cout; end if; if uins.nz='1’ then n <= out_ula(7); z <= is_zero(out_ula); end if;
end if; end process;
BLOCO DE CONTROLE• Função: gerar os sinais de controle para o bloco de dados,
em função da instrução corrente e dos flags de estado.
• Estrutura básica do bloco de controle:process begin wait until ck'event and ck='1';
-- fetch -- uins <= mar_pc; wait until ck'event and ck='1'; uins <= mdr_MmarP; wait until ck'event and ck='1'; uins <= ir_mdr; wait until ck'event and ck='1'; case ir is -- seleção pelo opcode when xxxx => uins <= ac_ac;
when others => null; end case; end process;
MICROINS E ESPERA
VO
LT
A
Espera o clock
SELECIONA
BLOCO DE CONTROLE
Vantagens deste estilo de descrição:
• Simples de descrever o controle: fetch seguido de case para seleção da operação.
• Fácil de realizar a temporização: basta inserir após cada microinstrução uma espera por borda de clock.
• Atenção: após a última microinstrução do ciclo de instrução não vai wait. Razão: antes do fetch já tem inserido um wait.
• Esta temporização permite instruções com número diferente de ciclos para execução, como é o caso da arquitetura proposta.
BC - Exemplo de instrução (1)
• De acordo com a especificação LDA, ADD, OR, AND são praticamente iguais
when ldaim | andim | orim | addim =>
uins <= mar_pc; wait until ck'event and ck='1';
uins <= mar_MmarP; wait until ck'event and ck='1';
sel_op (ir(7 downto 4), uins);
Função para escolha do microcomando em função dos 4 bits mais significativos
t0: MAR PCt1: MDR PMEM(MAR); PC++t2: AC AC op MDR setar flags
t0: MAR PCt1: MDR PMEM(MAR); PC++t2: AC AC op MDR setar flags
(1) continuação• Função para escolha do microcomando para LDA/ADD/OR/AND
• Inserir a função ou no package ou antes do begin
flags
procedure sel_op (signal ir: in std_logic_vector(3 downto 0);
signal uins : out microinstrucao ) is
begin
case ir is
when x"4" => uins <= (4, 1, 4, '0','0', ’ 1','0'); -- ac <- mdr
when x"5" => uins <= (4, 6, 0, '0','0', '1','1'); -- ac <- ac + mdr
when x"6" => uins <= (4, 6, 5, '0','0', '1','0'); -- ac <- ac or mdr
when x"7" => uins <= (4, 6, 6, '0','0', '1','0'); -- ac <- ac and mdr
when others => null;
end case;
end sel_op;
BC - Exemplo de instrução (2)• Micro código para os jumps (endereçamento direto)
• Trata-se todos os jumps juntos, no mesmo caso
when jcdir | jndir | jzdir =>
uins <= mar_pc; wait until ck'event and ck='1';
uins <= mdr_MmarP; wait until ck'event and ck='1';
if (((jc and c)='1') or ((jn and n)='1') or ((jz and z)='1')) then
uins <= pc_mdr;
else uins <= nop;
end if;
t0: MAR PCt1: MDR PMEM(MAR);t2: if(flag) then PC MDR
else PC++;
Crítica à implementação apresentada:
BC - Exemplo de instrução (3)
• Micro código para o HALT :
– implementa através de uma espera pelo reset
when hlt =>
while reset='0' loop
wait until ck'event and ck='1';
end loop;
As seqüências mar_pc, mdr_MmarP, e mdr_Mmar são repetidas inúmeras vezes. Poder-se-ia ter escrito um código mais estruturado.
ENTIDADE CPUentity cleopatra is
port( ck, reset: in std_logic; ce, rw, inicio : out std_logic; address: out regsize; datamem: inout regsize);
end cleopatra;
architecture cleopatra of cleopatra is component datapath is
port( uins : in microinstrucao; ck, reset: in std_logic;ir, address : out regsize; datamem : inout regsize;
n, z, c, v : out std_logic ); end component datapath; component control is
port( ir : in regsize; n, z, c, v, ck, reset: in std_logicuins : out microinstrucao;
); end component control; signal uins : microinstrucao; signal n,z,c,v : std_logic; signal ir : regsize; begin
ENTIDADE CPU
begin
ce <= uins.ce;rw <= uins.rw;
dp: datapath port map ( uins=>uins, ck=>ck, reset=>reset, ir=>ir, address=>address, datamem=>datamem, n=>n, z=>z, c=>c, v=>v);
ctrl: control port map ( ir=>ir, n=>n, z=>z, c=>c, v=>v, ck=>ck, reset=>reset, uins=>uins);
end cleopatra;
SINAIS PARA A MEMÓRIASINAIS PARA A MEMÓRIA
TEST BENCH (1)• Módulo responsável por gerar os vetores de teste para a simulação
• AÇÕES:
1 -- incluir a CPU no test_bench
2 -- gerar o clock
3 -- gerar o reset
4 -- ler da memória
5 -- escrever na memória, de maneira síncrona, como nos registradores
6 -- realizar a carga na memória quando acontece o reset
TEST BENCH (2)• IMPLEMENTAÇÃO:
architecture tb of tb is signal ck, reset, ce, rw, inicio: std_logic; signal address, data : regsize; file INFILE : TEXT open READ_MODE is "program.txt"; signal memoria : ram; signal ops, endereco : integer;begin
BLÁ, BLÁ, BLÁend tb
Desnecessário inicializar
Para carga do programa
TEST BENCH (3)1 -- incluir a CPU no test_bench cpu : cleopatra port map(ck=>ck, reset=>reset, ce=>ce, rw=>rw,
address=>address, datamem=>data);
2 -- gerar o clock process
begin ck <= '1', '0' after 10ns; wait for 20ns;
end process;
3 -- gerar o reset reset <= '1', '0' after 5ns ;
TEST BENCH (4)A MEMÓRIA É UM ARRAY, QUE É LIDO OU ESCRITO CONFORME OS
SINAIS CE E RW.
4 -- ler da memória
data <= memoria(CONV_INTEGER(address)) when ce='1' and rw='1' else "ZZZZZZZZ";
TEST BENCH (4 bis)
5 -- escrever na memória, de maneira síncrona, como nos registradores
• PROBLEMA para escrita - duas fontes de escrita: inicialização e Cleóptara.• Solução:
process(go, ce, rw, ck) begin if go'event and go='1' then if endereco>=0 and endereco <= 255 then memoria(endereco) <= conv_std_logic_vector(ops,8); end if; elsif ck'event and ck='0' and ce='1' and rw='0' then if CONV_INTEGER(address)>=0 and CONV_INTEGER(address) <= 255 then
memoria(CONV_INTEGER(address)) <= data; end if end if; end process;
escrita pelo test_bech
escrita pela Cleópatra
Importante: testar os limites da RAM
TEST BENCH (5)O PROGRAMA ARMAZENADO NA MEMÓRIA É CARREGADO
QUANDO O RESET ESTÁ ATIVO
6 -- realizar a carga na memória quando acontece o reset
process
variable IN_LINE : LINE; -- pointer to string variable linha : string(1 to 5); begin wait until reset = '1'; while NOT( endfile(INFILE)) loop -- end file checking readline(INFILE,IN_LINE); -- read line of a file read(IN_LINE, linha); decodifica a linha e gera o sinal “go” end loop; end process;
LAÇ
O D
E L
EIT
UR
A
SUBIDA DO RESET
TEST BENCH (6)• COMO CONVERTER A LINHA EM ENDEREÇO E DADO E GERAR
“GO” :case linha(1) is
when '0' => endereco <= 0;when '1' => endereco <= 1;
when 'F' => endereco <=15;when others => null;
end case;wait for 1 ps;
case linha(2) is when '0' => endereco <= endereco*16 + 0;when '1' => endereco <= endereco*16 + 1;
when 'F' => endereco <= endereco*16 + 15;when others => null;
end case;
-- linha (3) é espaço em branco
case linha(4) is when '0' => ops <= 0;when '1' => ops <= 1;
when 'F' => ops <=15;when others => null;
end case;wait for 1 ps; case linha(5) is when '0' => ops <= ops*16 + 0;
when '1' => ops <= ops*16 + 1; when 'F' => ops <= ops*16 + 15; when others => null;end case;wait for 1 ps;go <= '1'; wait for 1 ps;go <= ’0';
Fazer uma função para converter um char em inteiro
Pulso em “go” gera escrita na memória
SIMULAÇÃO (1) - PROGRAMA
• PROGRAMA (em código objeto)
00 40 ; endereço 00 LDA #01 98 ; endereço 01 H9802 54 ; endereço 02 ADD03 10 ; endereço 03 H1004 24 ; endereço 04 STA05 11 ; endereço 05 H1106 E0 ; endereço 06 HALT10 77 ; endereço 10 H77• FUNÇÃO DO PROGRAMA: somar a constante H98 ao
conteúdo do endereço H10 e depois gravar o resultado em H11
SIMULAÇÃO (2)
Colocou 98 no acumuladorno final da 1# instrução
Colocou 98 no acumuladorno final da 1# instrução
Soma da ac+mdrSoma da ac+mdrSoma inserida no MDR
para ser escrito na memória
Soma inserida no MDRpara ser escrito na memória
Gerou carry
Descida de Início indica nova instrução
LDA # H98ADD H10STA H11HALT10 77
Endereço 11HEndereço 11HEndereço 10H no MAREndereço 10H no MAR
HALTHALT
WRITEWRITE
Referências
• http://www.seas.upenn.edu/~ese201/vhdl/vhdl_primer.html
• Fernando Gehm Moraes e Ney Calazans, PUCRS, notas de aula.