定义旋转长度不固定的 rightrotate 函数

发布于 2024-11-15 03:25:51 字数 1591 浏览 2 评论 0原文

我需要 Verilog 中的 rightrotate 函数用于 32 位输入,因为它没有定义为运算符 (x >>> y)。

手动右旋转这样的输入很容易:

wire [31:0] test = 32'd12345; 
wire [31:0] rotated_1 = {test[0:0],test[31:1]};
wire [31:0] rotated_3 = {test[2:0],test[31:3]};

测试台的输出符合预期:

original: 00000000000000000011000000111001
rotate_1: 10000000000000000001100000011100
rotate_3: 00100000000000000000011000000111

我们看到,函数旋转(inp,x)应该像这样工作:

function rotate;
   input [31:0] inp; 
   input [4:0]  x;
   begin 
      rotate = {inp[x-1:0],inp[31:x]};
   end
endfunction

问题是:x不是常量,所以它不能编译。要使用 [a:b] 指定范围,a 和 b 都必须是常量。

解决方案似乎是使用参数:

function rotate;
   parameter integer x = 1;
   input [31:0] inp;
   begin
      rotate = {inp[x-1:0],inp[31:x]};
   end
endfunction

嗯,它确实可以编译,但与模块不同的是,您可以使用像这样更改的参数来实例化模块

param_module #(3) pm_inst(...);

不能与函数一起使用。事实上,通过阅读Verilog的语法,我看不到一种方法 all 来指定参数:

<function_call>
::= <name_of_function> ( <expression> <,<expression>>* )

我对 defparam 的实验仅适用于模块,不是功能。

由于 Verilog 中也不存在参数化宏,我应该如何实现旋转函数而不为每个可能的旋转声明一个? - 而且我需要很多这样的宏:-

(((不是 像这样:)

function rotate1...
function rotate2...
function rotate3...
...

I need a rightrotate function in Verilog for 32-Bit inputs, since it is not defined as an operator (x >>> y).

It is easy rightrotate such input by hand:

wire [31:0] test = 32'd12345; 
wire [31:0] rotated_1 = {test[0:0],test[31:1]};
wire [31:0] rotated_3 = {test[2:0],test[31:3]};

The output of a testbench is as expected:

original: 00000000000000000011000000111001
rotate_1: 10000000000000000001100000011100
rotate_3: 00100000000000000000011000000111

We see, that a function rotate(inp,x) should work like this:

function rotate;
   input [31:0] inp; 
   input [4:0]  x;
   begin 
      rotate = {inp[x-1:0],inp[31:x]};
   end
endfunction

Problem is: x is no constant, so it doesn't compile. To specify a range with [a:b], both a and b have to be constants.

A solution seems to be using parameters:

function rotate;
   parameter integer x = 1;
   input [31:0] inp;
   begin
      rotate = {inp[x-1:0],inp[31:x]};
   end
endfunction

Well, it does compile, but unlike modules, which you can instantiate with a changed parameter like this

param_module #(3) pm_inst(...);

,that does not work with functions. In fact, from reading the grammar of Verilog, I cannot see a way at all to specify the parameter:

<function_call>
::= <name_of_function> ( <expression> <,<expression>>* )

My experiments with defparam only worked with modules, not functions.

Since parametrized macros do not exist in Verilog either, how should i implement the rotate function without declaring one for each possible rotation? - and i need lots of them :-(

(Not like this:)

function rotate1...
function rotate2...
function rotate3...
...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吾家有女初长成 2024-11-22 03:25:51

您可以通过连接数据的两个副本并移位来模拟旋转:

function [31:0] rotate (input [31:0] data, input [4:0] shift);
reg [63:0] tmp;
begin
  tmp = {data, data} >> shift;
  rotate = tmp[31:0];
end
endfunction

You can simulate a rotate by concatenating two copies of the data and shifting:

function [31:0] rotate (input [31:0] data, input [4:0] shift);
reg [63:0] tmp;
begin
  tmp = {data, data} >> shift;
  rotate = tmp[31:0];
end
endfunction
柠檬 2024-11-22 03:25:51

阿罗哈!

简单的解决方案是使用输入的固定轮换为 0-31 步长的 MUX,然后使用 x 作为打开的值。

为了高效实施,请查看桶形移位器。使用五个 2-1 32 位 MUX,根据每个多路复用器的控制位,将输入链式移位 16、8、4、2、1 步(对于多路复用器 0、1、2、3、4)或不进行移位。

Aloha!

The simple solution is to use a MUX with fixed rotation in 0-31 steps of the input and then use x as the value to switch on.

For an efficient implementation take a look at the barrel shifter. Using five 2-1 32-bit MUXes in chain shifting the input either 16, 8, 4, 2, 1 steps (for mux 0, 1, 2, 3, 4) or not based on the control bit for each mux.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文