PROCESSADORES PROGRAMÁVEIS - como projetar um processador em VERILOG - Organização - parte 2

processador em VERILOG processadores em verilog Processadores programáveis
Este post faz parte da série Processadores programáveis. Leia também os outros posts da série:

Prezado leitor, daremos continuidade ao artigo anterior. Assim sendo, o presente artigo tem o intuito de discutir aspectos da organização de um processador multi-ciclo, de 16 bits, descrito em Verilog com um grupo (set) de 24 instruções e orientado a acumulador.

 

Antes de avançarmos diretamente sobre a organização é necessário estabelecer o conceito de Unidade de Controle (control) ou Bloco de Controle e o conceito de Caminho de Dados (datapath) ou Bloco Operacional. Segundo [1] podemos assumir de forma resumida que:

  • Unidade de Controle (control) ou Bloco de Controle comanda o Caminho de Dados, memórias e outros dispositivos que possuem entrada e saída (I\Os);
  • Caminho de dados realiza prioritariamente o armazenamento dos dados, operações (e.g. aritmética, multiplicação, rotação de bits, etc) e envolve tipos de dados não booleanos;

 

Já a Unidade de Controle, estamos falando agora de uma máquina de estados finitos ou FSM (Finite State Machine) que possui entradas, saídas, estados, ações executadas pelos estados e transições decorrentes da mudança desses estados. No decorrer deste artigo vamos retomar um pouco sobre esse assunto com exemplos concretos do nosso processador.

 

 

PENSANDO NA ORGANIZAÇÃO

 

Tendo em vista a arquitetura proposta no primeiro artigo, podemos começar estabelecendo os blocos funcionais de controle e caminho de dados e considerar que o nosso processador vai interagir com uma memória ROM e com uma RAM. A figura 1 ilustra os dois blocos funcionais do nosso projeto bem como a sua interface com o mundo externo. Na figura 1 é possível observar que os blocos funcionais control e datapath estão interligados às duas memórias e à interface do sistema através de barramentos de dados e fios/linha de dados, bem como a sinais de sistemas como o sinal de relógio e reset.

 

processador
Figura 1: Organização do Processador

 

 

 

Em um projeto de sistema digital uma das primeiras etapas que deve ser prevista (e não menos importante) é a interface do sistema. A opinião do presente autor é que: “uma interface bem definida poupa muita aspirina”. Então caro leitor, uma interface bem documentada e bem escrita poupa muito tempo e dinheiro de projeto. Neste momento já temos uma amostra de como será o nosso processador.

 

 

INTERFACE DO PROCESSADOR

 

Como mencionado anteriormente vamos detalhar melhor a interface do nosso sistema. Estabelecemos, portanto uma tabela com as informações mais relevantes para o nosso leitor. Na tabela 1 descrevemos o nome do sinal (NOME), qual o bloco que o sinal é utilizado (INTERFACE), se o sinal é uma entrada ou saída de dados (I/O), o tamanho do sinal em bits (BITS) e descrição funcional do sinal no sistema (DESCRIÇÃO).

 

 

Tabela 1: Interface do Processador

NOME

INTERFACE

I/O

BITS

DESCRIÇÃO

CLOCK_i

sistema

input

1

clock do sistema

RESET_n_i

sistema

input

1

Reset assíncrono – ativo em zero

ADDR_im_o

mem.instr.

output

10

Endereço para memória de instrução

DATA_im_i

mem.instr.

input

16

Dados vindos da memória de instrução

CEnable_im_o

mem.instr.

output

1

Habilita memória de instrução – ativa em zero

OEnable_im_o

mem.instr.

output

1

Habilita saída de dados da memória de instrução – ativa em zero

WEnable_dm_o

mem.dados

output

1

Habilita escrita na memória de dados – ativa em zero

CEnable_dm_o

mem.dados

output

1

Habilita a Memória de dados – ativa em zero

OEnable_dm_o

mem.dados

output

1

Habilita saída de dados da memória de dados – ativa em zero

ADDR_dm_o

mem.dados

output

11

Endereço da memória de dados

DATA_dm_i

mem.dados

input

16

Dados vindos da memória de dados

DATA_dm_o

mem.dados

output

16

Dados para memória de dados

 

 

Vale ressaltar que sempre que precisarmos de mais detalhes sobre o funcionamento de qualquer (e.g. memórias, RTCs, barramentos) sinal de uma interface externa podemos obtê-los através da folha de dados (datasheet) ou através de diagramas descritos por especialistas. Com relação às memória, neste artigo vamos optar em descrever graficamente os seus funcionamentos, tendo em vista que o protocolo utilizado tenta ser o mais genérico possível sem perder o foco em manter a similaridade com o que existe na indústria.

  

 

BLOCO DE CONTROLE ou UNIDADE DE CONTROLE

 

Amigo leitor, vamos focar agora em entender o bloco de controle. Neste momento já conseguimos vislumbrar mais detalhes das unidades funcionais do nosso projeto. Percebemos a necessidade de um bloco de somador figura 2 (a), um multiplexador figura 2 (b), uma forma de armazenarmos o endereço da instrução corrente (contador de programa ou PC figura 2 (c) ) e por fim precisamos do bloco de decodificação figura 2 (d). Para o leitor não achar que magicamente deduzimos isso fica a dica em observar como processador BIP [2] foi pensado, cuja arquitetura e organização nos inspiramos para esse artigo.

 

bloco_de_controle
Figura 2: Bloco de Controle do Processador

 

 

Ainda discutindo a figura 2, dois conjuntos de blocos precisam necessariamente ser descritos com mais detalhes. O conjunto que possui o bloco somador, multiplexador e PC e o bloco de decodificação. O nosso somador é responsável por incrementar o endereço da memória de programa. Este somador incrementa sempre em um bit (1 bit) o valor do nosso registro de 10 bits, ou seja, ele incrementa somando 1 até o registro atingir o fim das 1024 posições da memória (e.g. é importante observar que a arquitetura proposta tem o fim didático, portanto difere de arquiteturas que incrementam em um nibble o PC). Além disso, o somador não utiliza o transporte de bit (carry) e caso chegue ao fim do tamanho do registro ele reinicia com o valor zero (fica a dica ao leitor tratar esse overflow com mais propriedade). Seguindo o fluxo, o resultado do somador é então enviado de acordo com a entrada de seleção do multiplexador para o PC que por sua vez registra o próximo endereço da memória de instrução.

 

Já o bloco de decodificação nos é apresentado o conceito muito importante para um projetista de hardware, o de máquina de estados finitos. Vamos abordar com mais detalhes esse conceito a seguir. Para o nosso projeto vamos utilizar uma máquina de estados baseada em Mealy devido a algumas características interessantes dessa abordagem. Cabe, portanto ao nosso bloco de decodificação controlar o ritmo do nosso processador, controlando todos os sinais do bloco de Caminho de Dados.

 

 

MÁQUINA DE ESTADOS FINITOS – FSM (Finite State Machine)

 

Segundo [1] uma FSM é definida como um conjunto de estados que representa todos os estados, ou modos, possíveis de um sistema. Assim, uma FSM representa uma sequência de padrões de estados definidos em uma ordem pré-determinada pelo projetista de hardware. Existem dois modelos muito consolidados de máquinas estados, são as máquinas de estados de Moore e Mealy, vamos elaborar melhor a ideia a seguir.

 

 

MÁQUINA DE ESTADOS DE MOORE

 

Para [1] um circuito sequencial é chamado de máquina de estados de Moore quando são em função somente da saída.

 

moore
Figura 3: Arquitetura de bloco de controle usando FSM Moore

 

 

Uma alternativa para uma FSM Moore é uso de da FSM Mealy.

 

 

MÁQUINA DE ESTADOS DE MEALY

 

Um circuito sequencial é chamado de máquina de estados de Mealy quando a saída deste circuito além de depender do estado corrente ela também depende da entradas do circuito [1].

 

mealy
Figura 4: Arquitetura de bloco de controle usando FSM Mealy

 

 

 

MÁQUINA DE ESTADOS DO PROCESSADOR

 

Tendo em vista o que foi exposto, vamos agora definir qual será a “cara” da máquina de estados do nosso processador. Como mencionado anteriormente, o nosso processador deve obrigatoriamente executar uma sequência de operações armazenada na memória de programa. Assim, a Figura 5 ilustra essa sequência de estados de busca da instrução na memória de programa, decodificação dessa informação e execução da referida instrução conforme o opcode.

 

maquina_estados
Figura 5: Máquina de estados do processador

 

 

No estado de BUSCA iremos interagir com sinais da memória de instrução de forma a buscar a instrução conforme o endereço registrado no PC. O estado DECODIFICA tem o objetivo de “separar”  o campo OPCODE e o campo OPERANDO, ambos oriundos do barramento de dados da memória de instrução - DATA_im_i. Em posse de todas essas informações a nossa máquina de estados vai agora para o estado EXECUTA, que por sua vez tem o objetivo de executar a operação do referido OPCODE. Por fim a máquina de estados retorna para o estado de BUSCA, repetindo todo o ciclo novamente.

 

Aconselho ao amigo leitor a dar uma boa olhada em [3]. Este é um excelente trabalho que utilizei como referência para esse projeto. Neste trabalho, existe uma tabela na página 30 que mostra uma forma de documentar os sinais que serão trabalhados na parte 3 deste artigo e o estado de decodificação.

 

 

COMPARATIVO ENTRE MOORE E MEALY

 

Segundo [1] em uma máquina de estados de alto nível dizemos que Moore tem suas ações associadas apenas aos estados, ao passo que Mealy tem suas ações associadas a transições.

 

Moore também se caracteriza pela ausência de caminho combinacional entre a entrada e saída e por ser propensos a ter um caminho crítico mais curto. Já Mealy podemos fazer uma lista: (i) menor área* quando comparado a Moore, (ii) a saída computada automaticamente assim que ocorre um mudança nas entradas, (iii) Mealy é mais fácil de combinar circuitos maiores, (iv) a resposta de uma FSM Mealy é mais rápido que uma FSM Moore, entre outras características. Convido o leitor listar nos comentários deste artigo mais características entre as duas máquinas, fique à vontade. A figura 6 é uma boa forma de ilustrar os conceitos mencionados acima.

 

waveform
Figura 6: Exemplo de Mealy vs Moore - Waveform

 

 

Que os deuses da computação me perdoem, mas vou passar uma dica simples para lembrar a diferença entre as duas máquias (agradeço ao professor Daniel de BD02 - programa CI-brasil). Para lembrar de alguns conceitos entre as duas máquinas de estados basta associar Moore a uma vaca (vacas produzem mugidos, logo podemos associar ao som do mugido ao nome MOOre) e vacas ficam paradas. Já a máquina de estados de  Mealy podemos associar a uma ovelha (ovelhas são mais lépidas e ágeis). Assim, vacas são lentas e ficam mais paradas, o que nos leva a deduzir que a resposta de uma máquina de Moore é mais lenta ou parada quando comparada a Mealy, que por sua vez é mais saltitante. Já uma ovelha por ser menor é fisiologicamente mais complexa que uma vaca (eu pelo menos acho isso) teremos que inserir mais um sinal, no caso a saída também depende do sinal de entrada (não me pergunte como cheguei a essa associação).  

 

 

INTERFACE DO BLOCO DE CONTROLE

 

A tabela 2 descreve as informações mais importantes do nosso bloco de controle.

 

Tabela 2: Interface do bloco de controle do processador

NOME

INTERFACE

I/O

BITS

DESCRIÇÃO

CLOCK_i

Sistema

input

1

clock do sistema

RESET_n_i

Sistema

input

1

Reset assíncrono – ativo em zero

HOLD_n_i

Sistema

input

1

Mantém o estado do processador – ativo em zero

ADDR_im_o

Mem.instr.

output

10

Endereço para memória de instrução

DATA_im_i

Mem.instr.

input

16

Dados vindos da memória de instrução

CEnable_im_o

Mem.instr.

output

1

Habilita memória de instrução – ativa em zero

OEnable_im_o

Mem.instr.

output

1

Habilita saída de dados da memória de instrução – ativa em zero

WEnable_dm_o

Mem.dados

output

1

Habilita escrita na memória de dados – ativa em zero

CEnable_dm_o

Mem.dados

output

1

Habilita a Memória de dados – ativa em zero

OEnable_dm_o

Mem.dados

output

1

Habilita saída de dados da memória de dados – ativa em zero

Operand_o

Controle

output

11

Operando para mem.dados ou extensão de dados

Ext2PC_i

Datapath

input

16

Extensão de dados para o PC

N_i

Datapath

input

1

Sinal indicando resultado negativo da ULA

Z_i

Datapath

input

1

Sinal indicando resultado zero da ULA

Op_o

Controle

output

1

Operação ULA: 1 - adição/0 - subtração

WrAcc_o

Controle

output

1

Habilita a saída do registro Acumulador

SelB_o

Controle

output

1

Seleciona saída do mux2x1

SelA_o

Controle

output

3

Seleciona saída do mux3x1

branch

Controle

internal

1

Seleciona saída do mux2x1 de acordo com a operação de branch

WrPC

Controle

internal

1

Habilita a saída do registro Contador de Programa

opcode

Controle

internal

5

Código da operação

 

 

Vale a pena descrever um pouco mais alguns sinais são que internos descritos na tabela 2. O barramento de cinco bits opcode corresponde aos cinco bits mais significativos oriundos do barramento DATA_im_i, ou seja, o dado oriundo da memória de dados. Já o sinal branch tem por objetivo selecionar a saída do multiplexador 2x1 caso a instrução decodificada seja de desvio (e.g. JMP, BEQ, etc). Por fim o sinal WrPC tem por objetivo habilitar a saída do contador de programa (PC) após o fim de um ciclo do estágio e execução da máquina de estados.

 

 

DATAPATH ou BLOCO OPERACIONAL

 

Prezado leitor, antes de avançarmos sobre a nossa proposta de datapath, vamos esclarecer mais o conceito de processador de propósitos gerais. Segundo [1] um processador de propósito gerais difere de um processador de propósito único por armazenar a  tarefa de processamento em uma memória ao invés de ser construída no próprio circuito. Neste sentido devemos considerar que em todo o processamento os dados devem ser carregados, transformados e por fim armazenados conforme a operação executada. Nesse sentido um processador programável deve ter a capacidade de alimentar um bloco operacional para transformar esses dados recuperados da memória de programa. Tudo isto se dá utilizando circuitos básicos dentro do datapath utilizando uma ULA e um registrador de armazenamento dos resultados executados pela ULA e outros blocos funcionais. A figura 7 ilustra como foi organizado o datapath do nosso processador.

 

datapath
Figura 7: Datapath do processador

 

 

Descrevendo melhor a Figura 7 podemos observar alguns blocos muito interessantes. O bloco EXTENSION figura 7 (c) tem o intuito de preencher os 5 bits mais significativos do campo operando (Operando_i) com bits 1. Já os blocos de multiplexação figura 7 (b) e (c) atuam conforme o opcode que chega no bloco de controle (na parte 3 deste artigo será mais fácil visualizar como isso ocorre). O bloco ACC figura 7 (d) corresponde ao nosso bloco de acumulação do resultado da ULA ou da oriunda informação da memória de dados. O bloco ACC possui 16 bits (dois octetos), armazena temporariamente a informação e sua saída é ligada diretamente em uma das entradas da ULA. Para o leitor que curte acompanhar um pouco sobre a familia Intel x86, vai lembrar que em 1979 o primeiro processador Intel 8086 também possui um acumulador de 16 bits o registro AX, vale a pena dar uma olhada na folha de dados [4].

 

Agora vamos focar um pouco nas operações da ULA - Unidade Lógica Aritimética. A ULA da figura 7 (e) necessariamente recebe dois dados de 16 bits  e transforma essa informação em outro resultado de 16 bits conforme a operação selecionada. As operações trabalhadas no nosso projeto são: (i) soma, (ii) subtração, (iii) negação, (iv) (v) lógica and, (vi) lógica ou, (vii) lógica ou-exclusivo, (viii) rotação para a esquerda e (ix) rotação para a direita. A figura 8 ilustra a organização escolhida para a ULA.

 

ula
Figura 8: Unidade Lógica Aritmética do Processador

 

 

Na figura 8 é possível observar as operações típicas da ULA, sendo a saída de cada operação dependente necessariamente do valor do sinal Sel_i.

 

 

INTERFACE DO BLOCO DE CONTROLE

 

A tabela 3 descreve as informações mais importantes do nosso bloco de caminho de dados.

 

Tabela 3: Interface do bloco de caminho de dados

NOME

INTERFACE

I/O

BITS

DESCRIÇÃO

CLOCK_i

Sistema

input

1

clock do sistema

RESET_n_i

Sistema

input

1

Reset assíncrono – ativo em zero

ADDR_dm_i

Mem.dados.

input

11

Endereço para memória de dados

DATA_dm_i

Mem.dados.

input

16

Dados vindos da memória de instrução

DATA_dm_o

Mem.dados

output

16

Dados enviados para a memória de dados

Ext2PC_o

Datapath

output

16

Envia operando ao bloco de controle

Op_i

Controle

input

1

Seleciona o modo de operação da ULA

WrAcc_i

Controle

input

1

Habilita a saída do registro Acumulador

SelA_i

Controle

input

2

Seleciona qual a saída do multiplexador 3x1

SelB_i

Controle

input

1

Seleciona qual a saída do multiplexador 2x1

N_o

Datapath

output

1

Flag de número negativo ou não do resultado da ULA

Z_o

Datapath

output

1

Flag de zero ou não do resultado da ULA

waluout2mux3x1

Datapath

interno

16

Conecta ULA com MUX3x1

wdata2mux3x1

Datapath

interno

16

Conecta o barramento DATA_dm_i com MUX3x1

woperand

Datapath

interno

16

Conecta o sinal Operand_i com ADDR_dm_i e o bloco de extensão de sinal

waccout

Datapath

interno

16

Conecta a saída do acumulador com o barramento DATA_dm_o

wmux2x1alu

Datapath

interno

16

Conecta a saída do MUX2x1 com a ULA

 

 

Prezado leitor, como você pode perceber foi estipulado um padrão na nomenclatura  dos sinais internos, portas de entrada e saída para este projeto. Os sinais internos são em letra minúsculas, iniciam com a letra w, seguido do nome do bloco de origem para (número 2) o destino, por exemplo: wdata2mux3x1, um sinal interno (w) que liga dados para o MUX3x1. Os sinais de entrada e saída começam com o nome do sinal em letra maiúscula, seguido do caracter unde-line e o nome do bloco em minúsculo e por fim a letra i (input) ou o (output), por exemplo: DATA_dm_i, barramento de dados(DATA) do bloco memória de dados (dm) e por fim é um sinal de entrada (i).

 

Cada equipe de projeto, empresa e universidade utiliza um padrão específico. Contudo acredito que a melhor referência serão sempre os padrões IEEE, como Verilog-95, Verilog 2001 e 2005. Em média são 800 páginas de bons conhecimentos, vale a pena pesquisar no google sobre o assunto (sugiro a seguinte pesquisa: IEEE 1364 filetype: pdf ) os resultados são interessantes. Na próxima publicação vamos trabalhar um pouco mais sobre as linguagens de descrição de hardware.

 

 

INTERFACE DE MEMÓRIAS

 

As memórias são um caso a parte durante a fase da especificação projeto. Os requisitos de projeto devem estar bem definidos,  bem como o escopo do projeto. Existem engenheiros especializados no assunto (o que não é o caso do presente autor, por enquanto) e levaram anos para conseguir um conhecimento sólido no assunto, portanto iremos abordar pouco, quando comparado ao tamanho e relevância do assunto.

 

No contexto deste projeto, necessitamos de uma memória onde as tarefas de processamento (firmware**) devem ficar armazenadas mesmo após o completo desligamento do sistema, portanto necessitamos de uma memória de somente leitura - ROM (Read-Only Memory). O mesmo pode ser aplicado às informações já processadas pelo nosso sistema. Essas informações precisam ser armazenadas ou lidas novamente em determinadas situações em determinadas áreas de memória, são portanto armazenadas em uma memória de acesso randômico - RAM. Explicando de forma resumida, os dados podem ser armazenados (escrita do dado) e recuperados (leitura do dado) em qualquer endereço da RAM.

 

Os protocolo dessas memórias são baseados em diagramas de memórias de uma fabricante de semi-condutores (fica a dica para o leitor procurar mais detalhes sobre a XFAB, Samsung, TSMC , UMC, entre outras). Como existem restrições jurídicas para reprodução dessas informações, as figuras a seguir foram então adaptadas para esse artigo.  Devemos dar o mérito do conhecimento sobre o assunto ao programa CI-Brasil em especial aos instrutores e ao corpo administrativo que me toleraram por um ano.

 

 

ROM

 

A figura 9 ilustra o comportamento necessário para a leitura das informações armazenadas na memória ROM do nosso sistema.

 

rom
Figura 9 : Leitura da memória de instrução - ROM

 

 

Vamos agora descrever um pouco o comportamento dessa memória. Podemos observar que assim que a nossa memória é habilitada através do sinal CEnable_im_o em nível baixo (ou seja, o sinal se desloca para nível lógico zero)  o endereço é escrito no barramento ADDR_im_o (leitor lembre que o endereço é a informação armazenada do nosso PC) e na subida seguinte do ciclo de relógio é a vez do sinal OEnable_im_o se deslocar para o nível zero. Por fim no ciclo seguinte de relógio o dado requisitado é disponibilizado no barramento DATA_im_i.

 

 

RAM

 

A figura 10 ilustra o comportamento necessário para a leitura das informações armazenadas na memória RAM do nosso sistema. É possível observar que ela se assemelha ao comportamento da leitura da memória ROM (figura 9).

 

ram
Figura 10 : Leitura da memória de dados - RAM

 

 

Em se tratando da escrita na memória RAM temos algumas particularidades. As informações de endereço e os dados a serem escritos devem estar disponíveis nos respectivos barramentos ADDR_dm_o e DATA_dm_o antes que o sinal WEnable_dm_o transite do nível um para o zero. Vale observar que enquanto o sinal WEnable_dm_o estiver em nível alto, ambos os sinais podem transitar sem prejuízo de escrita indevida na memória.

 

ram_escrita
 Figura 11 : Escrita na memória de dados -RAM

 

 

Em nenhum momento foi discutido o aspecto de timming do projeto bem como as quantidades de ciclos que necessariamente uma memória pode requerer, tanto para escrita quanto para a leitura. Lembrando novamente que o projeto proposto é didático e muito do mundo real foi suprimido para um melhor entendimento e leitura do artigo. Nesse sentido convido ao leitor desbravar sobre o assunto e nos ajudar com bons comentários.

 

 

PRÓXIMA PUBLICAÇÃO

 

A próxima publicação (Implementação em VERILOG e simulação utilizando MODELSIM – Parte 3) iremos dar continuidade a este artigo. Iremos elaborar mais a ideia de como codificar em VERILOG, os aspectos peculiares da linguagem e por fim como produzir uma simulação da arquitetura proposta até agora. Agradeço o tempo que o amigo leitor tem dedicado a este artigo e espero que a leitura esteja suave e útil, afinal de contas, se não é útil para alguém então não tem necessidade de ser escrito.

  

*Mealy pode resultar em menos estados quando comparado com Moore, o que nos leva a concluir que menos lógica pode ser inserida no projeto.

 

 

Referências

 

[0] https://www.embarcados.com.br/processadores-programaveis-verilog-arquitetura-1/

[1] Sistemas Digitais - Projeto, Otimização e Hdls - Frank Vahid, ed.Artmed, 2008.

[2] http://bipide.com.br/

[3] PEREIRA, M. C. ; ZEFERINO, C. A. . uBIP: Microcontrolador Básico para o Ensino de Sistemas Embarcados. Itajaí: Universidade do Vale do Itajaí, 2008 (Trabalho de Conclusão de Curso).

[4] 8086 16-BIT HMOS MICROPROCESSOR 8086/8086-2/8086-1

Outros artigos da série

<< PROCESSADORES PROGRAMÁVEIS - como projetar um processador em VERILOG - Arquitetura - parte 1PROCESSADORES PROGRAMÁVEIS - como projetar um processador em VERILOG - Codificação - parte 3 >>
Este post faz da série Processadores programáveis. Leia também os outros posts da série:
NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Rodrigo Pereira
Engenheiro da Computação e Mestre em Computação Aplicada, cursou o programa Brasil-IP e CI-Brasil em Campinas/SP. Atualmente cursa doutorado junto ao PPGeEL - UFSC. Possui experiência no desenvolvimento e projeto de hardware e firmware para sistemas embarcados. Jornalista freelancer, curte praia e conhecer outros lugares. No tempo livre respira aviação. Amo meu filho, Francisco.

3
Deixe um comentário

avatar
 
2 Comment threads
1 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
Rodrigo Vinicius Mendonca PereWillian HenriqueTutorial de Verilog - Operadores Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
trackback

[…] PROCESSADORES PROGRAMÁVEIS - como projetar um processador em VERILOG - Organização - parte 2 […]

Willian Henrique
Visitante
Willian Henrique

Realmente muito bom o artigo, parabéns pelo trabalho.

Rodrigo Vinicius Mendonca Pere
Visitante
Rodrigo Vinicius Mendonca Pere

Obrigado Willian