我目前正在尝试使用两个while循环编译一个移位器。 For循环,移位功能和日志功能是不可能的。但是,当我尝试编译它时,它会在指示的行处抛出一个“带有非恒定循环条件的循环”错误。该行的while条件是i <1。 j,其中j是N-1,N是参数。我的问题是,由于N是一个参数,为什么即使在编译时它也不是常量,因此被认为是一个恒定的循环条件?
以下是代码:
module shifter(input logic [0:0] SW0, SW1, SW2, SW3, SW4, SW5, SW6, SW7, SW8, SW9, SW10,
input logic [0:0] KEY0, KEY1,
output logic [0:0] LEDG0, LEDG1, LEDG2, LEDG3, LEDG4, LEDG5, LEDG6, LEDG7);
parameter N=8;
//receive input from switches
logic [7:0] bits = '0;
logic [7:0] out = '0;
logic [0:0] move = '0;
logic [2:0] shift = '0;
logic next = 1;
always_comb
begin
bits[7] = SW7[0];
bits[6] = SW6[0];
bits[5] = SW5[0];
bits[4] = SW4[0];
bits[3] = SW3[0];
bits[2] = SW2[0];
bits[1] = SW1[0];
bits[0] = SW0[0];
shift[2] = SW10[0];
shift[1] = SW9[0];
shift[0] = SW8[0];
end
logic i = 0;
logic k = 0;
logic [31:0] j = N - 1;
always@(negedge KEY0)
begin
k <= shift[2:0];
do
begin
move <= bits[0];
do
begin
bits[i] <= bits[next];
i <= i + 1;
next <= i + 1;
end
while (i < j); //<-------indicated line
bits[7] <= move;
k <= k - 1;
end
while(k > 0);
out <= bits;
end
always_comb
begin
LEDG0 = out[0];
LEDG1 = out[1];
LEDG2 = out[2];
LEDG3 = out[3];
LEDG4 = out[4];
LEDG5 = out[5];
LEDG6 = out[6];
LEDG7 = out[7];
end
endmodule
答案 0 :(得分:1)
问题不在于j
,您可以通过将其声明更改为参数来轻松解决此问题:
parameter j = N -1;
真正的问题在于i
,并且您正在使用i
的非阻止分配。因此while
进入无限循环,因为(i<j)
永远不会有机会改变 - 它总是为0。
您需要采用不同的方法解决此问题。
答案 1 :(得分:0)
几个问题:
i
,k
和next
被定义为单个位。它们不能保持高于1的值。将它们声明为:
parameter j = N - 1;
bit [$clog2(N):0] next = 1;
bit [$clog2(N):0] i = 0;
logic [2:0] k = 0;
分配i
,k
和next
时,您需要使用屏蔽分配(=
)。非阻塞(<=
)推迟更新;每个循环将评估i<j
,k>0
,i + 1;
及其前negedge KEY0
值。
出于与move
,bits
和i
相同的原因,还应在k
和next
的作业中使用屏蔽作业。 。
i
和next
需要为k
的每个循环设置为0和1。
bits
分配了两个不同的always块,因此无法合成。
k
循环不能静态展开,这也意味着它不会合成
您可以通过将循环逻辑从always@(negedge KEY0)
移动到已分配always_comb
的{{1}}的底部来解决第2,3,4和5点。然后将非阻塞更改为阻止移动的逻辑。
据我所知,并非每个合成器都支持while循环。即使您的合成器支持while循环,它也必须静态展开;所有可合成循环的要求。
我猜这是一个任务,你的教练要求你做一个没有for循环的移位器。有一种方法可以在没有任何循环的情况下完成这项任务,并且可以使用比现在少得多的代码和变量行来减少它。我不会给你代码因为我认为这是作业。我建议调查并比较以下概念:
bits
陈述case
)和算术降档(>>
)运算符>>>
),也可称为范围切片您可能还想阅读比特连接(例如:+:
)和复制器(例如:{a,b}
)。