Como é sabido, VHDL é uma linguagem extremamente “tipada”, o que faz com que seja necessário escrever muito para dizer pouco.
Quase todos, cerca de 90% de meus designs em VHDL seguem um padrão: eles possuem uma máquina de estados, dois processes, sendo um para a parte combinacional e outra para a parte sequencial do design, bibliotecas básicas de aritmética (numeric.std) e lógica (1164), a parte combinacional recebendo a sequencial, etc. Esse estilo de codificação segue muito o que Pong. P Chu propõe em seu livro RTL Hardware Design using VHDL. E quando algo é padrão, nada melhor do que fazer um script para diminuir a parte burocrática de escrever um novo módulo em VHDL e ir direto ao que interessa.
Para ficar simples, me limitei a geração automática da interface da entidade (sinais de entrada/saída), maquina de estados, processo combinacional e sequencial e registradores a partir de um arquivo .txt.
Pensei em automatizar muita coisa mas a complexidade tanto do .txt responsável por gerar o VHDL quanto a do software em Python iria aumentar muito e não ficaria mais algo simples de se utilizar, perderia o “charme”.
Funcionamento
A sintaxe do arquivo .txt é bem simplificada, a primeira linha é o nome da entidade, a segunda o clock e a terceira o reset. As demais linhas são sinais de entrada ou saída da entidade até chegar no “#” após o símbolo “#” as linhas viram sinais dentro do design.
Da segunda linha em diante o último parâmetro (após o -) é o número de bits.
Para rodar o script basta executar o arquivo vhdl_gen.py e passar o caminho para o arquivo .txt como parâmetro.
Exemplo
A partir deste arquivo blink_led.txt de 8 linhas:
blink_led sysclk-in-1 reset_n-in-1 enable-in-1 leds-out-16 # timer-16 leds-16
É gerado este arquivo .vhd de 74 linhas:
--Libraries and use clauses library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity blink_led is port ( sysclk : in std_logic; reset_n : in std_logic; enable : in std_logic; leds : out std_logic_vector(15 downto 0) ); end blink_led; ------------------------------------------------------ architecture rtl of blink_led is type STATE_MACHINE_TYPE is (S0,S1,S2,S3); attribute SYN_ENCODING : string; attribute SYN_ENCODING of STATE_MACHINE_TYPE : type is "safe"; signal state : STATE_MACHINE_TYPE; signal state_next : STATE_MACHINE_TYPE; signal timer_reg : std_logic_vector(15 downto 0); signal timer_next : std_logic_vector(15 downto 0); signal leds_reg : std_logic_vector(15 downto 0); signal leds_next : std_logic_vector(15 downto 0); begin -- Sequential process process(sysclk, reset_n) is begin if (reset_n = '0') then state <= S0; elsif rising_edge(sysclk) then timer_reg <= timer_next; leds_reg <= leds_next; state <= state_next; end if; end process; -- Combinational process process(state, timer_reg, leds_reg) is begin timer_next <= timer_reg; leds_next <= leds_reg; state_next <= state; case state is when S0 => null; when S1 => null; when S2 => null; when S3 => null; when OTHERS => null; end case; end process; end rtl;
Conclusões
Em um livro que li devido a muitas recomendações (The Pragmatic Programmer) há capítulos dedicados a geradores de códigos e aos benefícios proporcionados ao utilizar um gerador de código, alguns deles:
-
Expressar a mesma informação somente uma vez (DRY do not repeat yourself);
-
Menor tempo de desenvolvimento pois não é necessário escrever tanto;
-
Menos sucessível a erros de sintaxe;
-
Padronização no código fonte de um projeto e etc.
Recomendo este livro, apesar de não ser direcionado a desenvolvedores de hardware ele possui uma linguagem muito boa e dicas gerais de desenvolvimento que também podem ser aproveitadas para o desenvolvimento de sistemas de hardware.
Agradeço ao Fabio, Vinicius e o Vitor pelas contribuições no projeto, que o deixaram muito melhor.
E por último fica aqui o link para o gerador de VHDL feito em Python. Funciona em Windows e Linux, fiquem a vontade para usar, “forkar” e dar feedback. Recomendo ler o README com atenção.