【问题标题】:Rotate left verilog case旋转左verilog大小写
【发布时间】:2014-01-17 17:17:58
【问题描述】:

我的任务是用verilog 写一个16 位的ALU。当我做需要旋转操作数和做 2 的补码加减法的部分时,我发现了困难。我知道如何用纸和铅笔解决这个问题,但我无法在 Verilog 中找到解决方法。 例如: A表示为a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 如果我要旋转 4 位, 答案是 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 a15 a14 a13 a12

我尝试了串联,但结果是不正确的。 需要大家帮忙...

【问题讨论】:

标签: rotation verilog shift


【解决方案1】:

以下将使用一个移位器工作:

assign A_out = {A_in,A_in} >> (16-shift[3:0]);

shift 为 0 时,选择左侧的 A_in。随着shift 的增加,左侧A_in 向左移动,右侧A_in 的MSB 填充。

如果进行综合,那么您可能需要使用多路复用器,因为动态移位逻辑往往需要更多门。 16 位 barrel shifter 需要 4 级 2 对 1 多路复用器。

wire [15:0] tmp [3:1];
assign tmp[3] = shift[3] ? {  A_in[ 7:0],  A_in[15: 8]} : A_in;
assign tmp[2] = shift[2] ? {tmp[3][11:0],tmp[3][15:12]} : tmp[3];
assign tmp[1] = shift[1] ? {tmp[2][13:0],tmp[2][15:14]} : tmp[2];
assign A_out  = shift[0] ? {tmp[1][14:0],tmp[1][15   ]} : tmp[1];

【讨论】:

  • 这不是倒退吗?在我看来,移位运算符绑定到右侧A_in,从而减少了它的长度。如果shift 为0,则将A_in 右移regsize - shift 位将移动regsize 位,从而留下一个0 位长的表达式,concat 运算符用隐式截断的左A_in 填充,留下A_in。如果 shift 为 1 到 regsize,则向右移动 A_in by regsize - shift` 位将在右侧留下 shift 位,因此左侧 A_in 仅填充 regsize - shift 位,从而导致整体向左旋转 @987654340 @比特。
【解决方案2】:

为什么连接不正确?这应该可以满足您的要求。

 assign A_out[15:0] = {A_in[11:0], A_in[15:12]};

【讨论】:

  • 其实就是一个例子。在实验室中,要旋转的位数是随机的,我尝试输入类似 assign A_out[15:0] = {A_in[15-n:0], A_in[15:15-n+1]};编译器说它超出了界限。我不知道如何解决
  • 是的,以这种方式选择可变部分是不合法的。
【解决方案3】:
assign A_out = A_in << bits_to_rotate;

其中bits_to_rotate 可以是变量值(信号或reg)。 这将推断出使用多路复用器或桶形移位器的通用移位器,无论它更适合目标硬件。合成器会处理这个问题。


哦,好吧。如果你想旋转而不是移位,事情就有点棘手了:

assign A_out = (A_in << bits_to_rotate) | (A_in >> ~bits_to_rotate);

【讨论】:

  • ">" 用于换档,不是吗?如果我要使用它,它会复制右移或左移功能吗?
  • 是的,它们正是为此目的。当您将这些运算符与表达式右侧的常量一起使用时,它们的行为与串联运算符方法相同(实际上,它们被合成,就像使用串联运算符一样)。这些运算符的好处是您可以在右侧放置一个变量表达式,然后合成器将推断出一个合适的(通常是桶形)移位器。
  • 这很接近,但我认为~ 没有正确的运算符。如果要向左旋转 1,则需要 >15。 ~4'b0001 = 4'b1110 (14)。应该是&gt;&gt;(16-bits_to_rotate)
  • 或 (~bits_to_rotate +1)
【解决方案4】:

我发现做到这一点的最好方法是找到一个模式。当您想将 8 位信号向左旋转 1 位 (8'b00001111 &lt;&lt; 1) 时,结果为 8'b00011110),当您想向左旋转 9 位 (8'b00001111 &lt;&lt; 9) 时,结果相同,8'b00011110,还有轮换 17 个位置,这减少了您下一张桌子的可能性:

因此,如果您看一下,相当于旋转 1 个位置的所有数字的前三位 (1,9,17,25...249) 等于 001 (1)。

表上所有数字的前三位相当于循环 6 个位置 (6,14,22,30...254) 等于 110 (6)。

因此,您可以应用掩码 (8'b00000111) 来确定正确的移位,方法是将所有其他位设为零:

reg_out_temp <= reg_in_1 << (reg_in_2 & 8'h07);

reg_out_temp shallreg_in_1 的双倍,在这种情况下 reg_out_temp shall 是 16 位和 reg_in_1 8 位,所以你可以得到当您移动数据时将携带的位转移到另一个字节,以便您可以使用 OR 表达式将它们组合起来:

reg_out <= reg_out_temp[15:8] | reg_out_temp[7:0];

因此,通过两个时钟周期,您就有了结果。对于 16 位旋转,您的掩码应为 8'b00011111 (8'h1F),因为您的移位从 0 变为 16,并且您的临时寄存器应为 32 位。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-13
    • 2011-01-16
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    相关资源
    最近更新 更多