Pergunta

Usando o código pseudo aqui. Existem prós e contras nesses estilos:

Digamos que você tenha um ALU que possa acrescentar e, ou e xor. É melhor ter código que calcule as respostas possíveis o tempo todo do que selecione a resposta com base no código OPC (neste caso, um quente):

alu_add = a + b;
alu_and = a & b;
alu_or  = a | b;
alu_xor = a ^ b;

...

if(opcode[0])      alu_out = alu_add;
else if(opcode[1]) alu_out = alu_and;
else if(opcode[2]) alu_out = alu_or;
else if(opcode[3]) alu_out = alu_xor;

Uma alternativa seria codificar assim:

if(opcode[0])      alu_out = a + b;
else if(opcode[1]) alu_out = a & b;
else if(opcode[2]) alu_out = a | b;
else if(opcode[3]) alu_out = a ^ b;

Eu também vi isso como:

alu_add = a + b;
alu_and = a & b;
alu_or  = a | b;
alu_xor = a ^ b;

...

alu_out = 
  ( 8{opcode[0]} & alu_add ) |
  ( 8{opcode[1]} & alu_and ) | 
  ( 8{opcode[2]} & alu_or ) |
  ( 8{opcode[3]} & alu_xor );

Existem prós e contras para o método ou eles saem o mesmo no final?

Foi útil?

Solução

Pense nisso em termos de níveis de lógica e legibilidade. Os dois primeiros formulários são bons em termos de legibilidade, mas ambos incorporam prioridade desnecessariamente e resultarão em mais níveis de lógica. A terceira forma também não é tão maravilhosa por nenhuma dessas métricas. Por fim, não há motivo aparente para usar a codificação de um hots aqui sobre a codificação binária. Aqui está como eu codificaria isso:

parameter ALU_ADD = 2'b00;
parameter ALU_AND = 2'b01;
parameter ALU_OR  = 2'b10;
parameter ALU_XOR = 2'b11;

reg [1:0]  opcode;  // 2 bits for binary coding vs. 4 for one-hot

// e mais tarde, em seu sempre bloqueio:

case (opcode)  // synopsys parallel_case
    ALU_ADD: alu_out = a + b;
    ALU_AND: alu_out = a & b;
    ALU_OR:  alu_out = a | b;
    ALU_XOR: alu_out = a ^ b;
endcase

Aqui, atribuí explicitamente valores aos códigos de operações da Alu, evitando "números mágicos" e facilitando a compreensão do que está acontecendo. Também usei a instrução CASE e apliquei uma diretiva que informa à minha ferramenta de síntese que não mais que uma expressão pode ser correspondida, para que nenhum codificador de prioridade seja inferido. Não nomeei os sinais intermediários (ALU_ADD etc.) porque são operações triviais, mas frequentemente o faço quando quero acesso conveniente a esses sinais (vendo seus valores após a simulação em um visualizador de forma de onda, por exemplo).

Você pode aprender mais sobre o uso de declarações de caso de maneira eficaz em Este artigo do excelente Design Sunburst Site (sem afiliação, apenas um ex -aluno).

Por fim, sobre sua pergunta, "é melhor ter código que calcule as respostas possíveis o tempo todo e selecione a resposta com base no código OPCOD" - lembre -se de que o Verilog é um idioma de descrição de hardware. Todas as implementações nesta página estão calculando tudo o tempo todo. Onde eles diferem está nos níveis de lógica e legibilidade. Dar uma olhada em esta página, que mostra que minha implementação tem 1 nível de lógica além das próprias operações, onde a implementação do IF-ELSE tem 3 níveis adicionais de lógica.

Outras dicas

Os dois primeiros darão a mesma lógica, mas você receberá uma trava alu_out Porque o seu if else Block (seu codificador de prioridade) não tem final else. (Isso é verdade para o Verilog de qualquer maneira). Se o seu tempo estiver apertado, você pode ter problemas com os caminhos longos que um codificador prioritário implica.

Na terceira versão, você obterá uma estrutura mais 'paralela', que pode ser melhor para o tempo. Não vai travar.

Nas três versões, cada uma das quatro operações estará apagando nomatter o que o código OPC. Isso terá implicações de poder.

É minha opinião que a primeira versão ganha para maior clareza e você pode obter cada uma das operações separadas no seu visualizador de forma de onda ao depurar. Não faz sentido codificar algo que não é tão fácil de ler, a menos que as restrições de tempo, área ou energia estejam sofrendo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top