计算结果和多路复用

old*_*mer 4 optimization verilog vhdl

在这里使用伪代码.这些风格是否有利有弊:

假设你有一个可以添加的alu,和,或者和xor.它是最好有一个计算可能的答案所有的时间,然后选择基于操作码的答案代码(在这种情况下,一个热):

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;
Run Code Online (Sandbox Code Playgroud)

另一种方法是像这样编码:

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;
Run Code Online (Sandbox Code Playgroud)

我也看到它:

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 );
Run Code Online (Sandbox Code Playgroud)

这两种方法都有利有弊吗?或者它们最终会出现同样的问题?

jlf*_*jlf 8

从逻辑和可读性的角度考虑这一点.前两种形式在可读性方面很好,但两者都不必要地体现优先级,并将导致更多的逻辑层次.第三种形式也不是这些指标中的任何一种.最后,没有明显的理由在这里使用单热编码而不是二进制编码.这是我如何编码:

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
Run Code Online (Sandbox Code Playgroud)

//以及之后,在你的总是阻止:

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
Run Code Online (Sandbox Code Playgroud)

在这里,我明确地为ALU操作码指定了值,避免了"魔术数字",并让其他人更容易理解正在发生的事情.我还使用了case语句并应用了一个指令,该指令告诉我的综合工具只能匹配一个表达式,因此不会推断出优先级编码器.我没有命名中间信号(alu_add等),因为这些操作很简单,但是当我想要方便地访问这些信号时(例如在波形查看器中模拟后看到它们的值),我经常这样做.

您可以从优秀的Sunburst Design网站(没有任何关系,只是前学生)中了解有关在本文中有效使用案例陈述的更多信息.

最后,关于你的问题,"让代码一直计算可能的答案然后根据操作码选择答案是否更好" - 请记住,Verilog是一种硬件描述语言.无论如何,这个页面上的所有实现都在计算所有内容.它们的不同之处在于逻辑和可读性水平.看一下这个页面,它显示我的实现有超出操作本身的1级逻辑,其中if-else实现有3个额外的逻辑级别.