计算结果并进行复用或不复用
这里使用伪代码。这些风格有优点和缺点吗:
假设你有一个可以进行加法、与、或和异或运算的 alu。是否最好使用始终计算可能答案的代码,然后根据操作码选择答案(在本例中是一个热门答案):
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;
另一种方法是这样编码:
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;
我也将其视为:
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 );
有吗这两种方法各有利弊,还是最终结果相同?
Using pseudo code here. Are there pros and cons to these styles:
Say you have an alu that can do add, and, or and xor. Is it better to have code that computes the possible answers all the time then select the answer based on the opcode (in this case a one hot):
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;
An alternative would be to code it like this:
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;
I have also seen it as:
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 );
Are there pros and cons to either method or do they come out about the same in the end?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从逻辑和可读性的角度考虑这一点。前两种形式在可读性方面很好,但都不必要地体现了优先级,并且会导致更多层次的逻辑。从这两个指标来看,第三种形式也不是那么精彩。最后,没有明显的理由在此处使用 one-hot 编码而不是二进制编码。下面是我的编码方式:
// 以及稍后,在您的always块中:
这里我显式地为ALU操作码分配了值,避免了“幻数”并使其他人更容易理解正在发生的事情。我还使用了 case 语句并应用了一条指令,该指令告诉我的综合工具不能匹配多个表达式,因此不会推断出优先级编码器。我没有命名中间信号(alu_add 等),因为这些都是微不足道的操作,但当我想要方便地访问这些信号时(例如在波形查看器中仿真后查看它们的值),我经常这样做。
您可以在这篇文章中了解有关有效使用 case 语句的更多信息,该文章来自优秀的 Sunburst Design 网站(无隶属关系,只是以前的学生)。
最后,关于您的问题,“是否最好使用始终计算可能答案的代码,然后根据操作码选择答案”——请记住,Verilog 是一种硬件描述语言。无论如何,此页面上的所有实现始终都在计算所有内容。它们的不同之处在于逻辑级别和可读性。看看这个页面,这表明我的实现超出操作本身的 1 级逻辑,其中 if-else 实现具有 3 级附加逻辑。
Think about this in terms of levels of logic and readability. The first two forms are fine in terms of readability, but both embody priority unnecessarily and will result in more levels of logic. The third form is also not so wonderful by either of these metrics. Lastly, there's no apparent reason to use one-hot coding here over binary coding. Here's how I'd code this:
// and later, in your always block:
Here I've explicitly assigned values to the ALU opcodes, avoiding "magic numbers" and making it easier for others to understand what's happening. I've also used the case statement and applied a directive that tells my synthesis tool that no more than one expression can be matched, so no priority encoder will be inferred. I didn't name the intermediate signals (alu_add etc.) because these are trivial operations, but I frequently do so when I want convenient access to those signals (seeing their values after simulation in a waveform viewer for example).
You can learn more about using case statements effectively in this article from the excellent Sunburst Design site (no affiliation, just a former student).
Finally, about your question, "Is it better to have code that computes the possible answers all the time then select the answer based on the opcode" -- remember that Verilog is a hardware description language. All the implementations on this page are computing everything all the time anyway. Where they differ is in levels of logic and readability. Take a look at this page, which shows that my implementation has 1 level of logic beyond the operations themselves, where the if-else implementation has 3 additional levels of logic.
前两个将给出相同的逻辑,但您将在else< /代码>。 (无论如何,这对于 verilog 来说是正确的)。如果您的时间紧迫,您可能会遇到优先级编码器所暗示的长路径问题。
alu_out
上获得锁存器,因为您的if else
块(您的优先级编码器)没有最终的在第三个版本中,您将获得更加“并行”的结构,这可能更适合计时。它不会卡住。
在所有三个版本中,无论操作码是什么,四个操作中的每一个都将崩溃。这将会产生权力影响。
我认为第一个版本在清晰度方面胜出,您可以在调试时在波形查看器中查看每个单独的操作。除非时间、面积或功率限制受到损害,否则编写不易阅读的内容是没有意义的。
The first two will give the same logic, but you'll get a latch on
alu_out
because yourif else
block (your priority encoder) has no finalelse
. (This is true for verilog anyway). If your timing is tight, you may have issues with the long paths that a priority encoder implies.On the 3rd version, you'll get a more 'parallel' structure which may be better for timing. It won't latch.
In all three versions, each of the four operations will be clattering away nomatter what the opcode. This will have power implications.
It's my opinion that the first version wins for clarity, and you can get at each of the separate operations in your waveform viewer when debugging. There's no point in coding up something that is not as easy to read unless timing, area or power constraints are hurting.