bit-manipulation - Verilog 访问特定位

标签 bit-manipulation verilog

我在 Verilog 中访问 32 个最高有效位和 32 个最低有效位时遇到问题。我编写了以下代码,但出现错误“非法部分选择表达式” 这里的重点是我无法访问 64 位寄存器。能否请你帮忙。

`MLT: begin
  if (multState==0) begin
    {C,Res}<={A*B}[31:0];
    multState=1;
  end
  else
  begin
    {C,Res}<={A*B}[63:32];
    multState=2;  
  end

最佳答案

不幸的是,Verilog 的位选择和部分选择功能是表达式操作数的一部分。它们不是 Verilog 运算符(参见 Verilog 2005 Std. Document, IEEE Std 1364-2005 的第 5.2.1 节),因此不能应用于任意表达式,而只能直接应用于寄存器或连线。

有多种方法可以执行您想要的操作,但我建议使用临时 64 位变量:

wire [31:0] A, B;
reg  [63:0] tmp;
reg  [31:0] ab_lsb, ab_msb;

always @(posedge clk) begin
  tmp = A*B;
  ab_lsb <= tmp[31:0];
  ab_msb <= tmp[63:32];
end

(对 ab_lsb 和 ab_msb 的赋值可以是有条件的。否则,一个简单的“{ab_msb, ab_lsb} <= A*B;”当然也可以。)

请注意,我使用阻塞赋值来分配 'tmp',因为我需要以下两行中的值。这也意味着从外部访问 'tmp' 是不安全的
这总是阻止。

另请注意,此处不需要连接 hack {A*B},因为 A*B 已分配给 64 位寄存器。这也符合 IEEE Std 1364-2005 的 Sec 5.4.1 中的建议:

Multiplication may be performed without losing any overflow bits by assigning the result to something wide enough to hold it.



但是,您说:“这里的重点是我无法访问 64 位寄存器”。

所以我将描述一个不使用任何 Verilog 64 位寄存器的解决方案。但是,这不会对生成的硬件产生任何影响。它只会看起来不同
Verilog 代码。

这个想法是通过移位 A*B 的结果来访问 MSB 位。以下天真的版本将不起作用:
ab_msb <= (A*B) >> 32;  // Don't do this -- it won't work!

这不起作用的原因是 A*B 的宽度由赋值的左侧决定,即 32 位。因此 A*B 的结果将只包含结果的低 32 位。

使操作的位宽自行确定的一种方法是使用连接运算符:
ab_msb <= {A*B} >> 32;  // Don't do this -- it still won't work!

现在乘法的结果宽度是使用最大值确定的。其操作数的宽度。不幸的是,两个操作数都是 32 位,因此我们仍然有 32 位乘法。所以我们需要将一个操作数扩展为 64 位,例如通过附加零
(我假设无符号操作数):
ab_msb <= {{32'd0, A}*B} >> 32;

访问 lsb 位很容易,因为无论如何这是默认行为:
ab_lsb <= A*B;

所以我们最终得到以下替代代码:
wire [31:0] A, B;
reg  [31:0] ab_lsb, ab_msb;

always @(posedge clk) begin
  ab_lsb <= A*B;
  ab_msb <= {{32'd0, A}*B} >> 32;
end

Xilinx XST 14.2 为两个版本生成相同的 RTL 网表。我强烈推荐第一个版本,因为它更容易阅读和理解。如果只使用'ab_lsb' 或'ab_msb',综合工具将自动丢弃'tmp' 未使用的位。所以真的没有区别。

如果这不是您要查找的信息,您可能应该澄清“无法访问 64 位寄存器”的原因和方式。毕竟,您还尝试访问代码中 64 位值的位 [63:32]。由于您无法在不执行低 32 位所需的几乎所有计算的情况下计算乘积 A*B 的高 32 位,因此您可能会要求一些不可能的事情。

关于bit-manipulation - Verilog 访问特定位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16468114/

相关文章:

c - 有什么方法可以在数学上改进这个 C 按位​​函数吗?

verilog 生成 if/else

verilog - 具有独特参数的 SystemVerilog 接口(interface)数组

verilog - 在verilog中检测未分配的寄存器

verilog - 为什么不在 Verilog 中综合延迟?

verilog - 如何每 n 个时钟周期切换一个采样时钟?

c++ - 位操作的标准(跨平台)方式

java - 存储 "180-bit"(超过 64 位)整数的有效方法

c - 按位运算相当于大于运算符

c - 如何在 C 中实现移位运算的逆运算?