我如何在 Verilog 上制作可综合的参数化编码器?
How do i make a synthesizable parameterized encoder on Verilog?
我试过这样做:
module encoder
#(
parameter WIDTH = 4
)
(
input wire [WIDTH-1: 0] in,
output reg [$clog2(WIDTH)-1: 0] out
);
genvar i;
generate
for (i = 0;i < WIDTH;i = i+1)
begin :gen_block
always @*
begin
if (in[i]==1'b1)
out = i;
end
end
endgenerate
endmodule
在仿真中效果很好,但不知道能不能合成。 generate block 将生成 always block 的多个副本,我猜 [=] 的前一个值之间会有竞争条件17=]out 和 out.
的更新值
我假设此代码无法合成是否正确?如果是这样,我应该如何更改才能使其正确合成?
是的,您在模拟中确实存在竞争条件,而且它是不可综合的。您不能让多个 always
块并行地对同一个变量进行赋值(当 in
中设置了多个位时会发生这种情况)。您需要一个常规的程序 for 循环,而不是生成 for 循环。
module encoder
#(
parameter WIDTH = 4
)
(
input wire [WIDTH-1: 0] in,
output logic [$clog2(WIDTH)-1: 0] out
);
always_comb begin
out = 'x; // don't care if no 'in' bits set
for (int i = 0;i < WIDTH;i++)
if (in[i]==1'b1) begin
out = i;
break; // priority goes from LSB-to-MSB
end
end
endmodule
编辑:
对于尚不支持 break
的工具
always_comb begin
bit Break;
Break = 0;
out = 'x; // don't care if no 'in' bits set
for (int i = 0;i < WIDTH;i++)
if (in[i]==1'b1 && !Break) begin
out = i;
Break = 1;
end
end
你可以通过初始化 i = N-1 来避免中断
module encoder
#(
parameter WIDTH = 4
)
(
input wire [WIDTH-1: 0] in,
output logic [$clog2(WIDTH)-1: 0] out
);
always_comb begin
out = 'x; // don't care if no 'in' bits set
for (int i = N-1 ;i >=0;i--)
if (in[i]) begin
out = i;
end
end
endmodule
我试过这样做:
module encoder
#(
parameter WIDTH = 4
)
(
input wire [WIDTH-1: 0] in,
output reg [$clog2(WIDTH)-1: 0] out
);
genvar i;
generate
for (i = 0;i < WIDTH;i = i+1)
begin :gen_block
always @*
begin
if (in[i]==1'b1)
out = i;
end
end
endgenerate
endmodule
在仿真中效果很好,但不知道能不能合成。 generate block 将生成 always block 的多个副本,我猜 [=] 的前一个值之间会有竞争条件17=]out 和 out.
的更新值我假设此代码无法合成是否正确?如果是这样,我应该如何更改才能使其正确合成?
是的,您在模拟中确实存在竞争条件,而且它是不可综合的。您不能让多个 always
块并行地对同一个变量进行赋值(当 in
中设置了多个位时会发生这种情况)。您需要一个常规的程序 for 循环,而不是生成 for 循环。
module encoder
#(
parameter WIDTH = 4
)
(
input wire [WIDTH-1: 0] in,
output logic [$clog2(WIDTH)-1: 0] out
);
always_comb begin
out = 'x; // don't care if no 'in' bits set
for (int i = 0;i < WIDTH;i++)
if (in[i]==1'b1) begin
out = i;
break; // priority goes from LSB-to-MSB
end
end
endmodule
编辑:
对于尚不支持 break
always_comb begin
bit Break;
Break = 0;
out = 'x; // don't care if no 'in' bits set
for (int i = 0;i < WIDTH;i++)
if (in[i]==1'b1 && !Break) begin
out = i;
Break = 1;
end
end
你可以通过初始化 i = N-1 来避免中断
module encoder
#(
parameter WIDTH = 4
)
(
input wire [WIDTH-1: 0] in,
output logic [$clog2(WIDTH)-1: 0] out
);
always_comb begin
out = 'x; // don't care if no 'in' bits set
for (int i = N-1 ;i >=0;i--)
if (in[i]) begin
out = i;
end
end
endmodule