如何用不关心参数化 case 语句?
How to parameterize a case statement with don't cares?
我有一根叫做输入的电线,我想检测前导的数量
我正在尝试创建一个模块,该模块使用下面的 case 语句根据前导零的数量更改输出数据。但是输入的大小是可参数化的。
如果 X 是固定值 4,我会创建一个 case 语句,
case (input)
4'b0001 : o_data = {i_data[0]};
4'b001x : o_data = {i_data[1],1'b0};
4'b01xx : o_data = {i_data[2],2'b0};
4'b1xxx : o_data = {i_data[3],3'b0};
default : o_data = 4'b0000;
endcase
但是对于变量 X,我该如何定义所有情况?
这个问题与这个问题类似:How to define a parameterized multiplexer using SystemVerilog
你不能像那样真正参数化 case
语句,但你可以使用 for
循环代替:
module lead_detector #(parameter int WIDTH = 4) (
input logic[WIDTH - 1:0] in,
output logic[WIDTH - 1:0] out
);
always_comb begin
out = '0;
for (int i = WIDTH - 1; i >= 0; i--)
if (in[i] == 1'b1) begin
out[i] = 1;
break;
end
end
endmodule
这是我看到我的设计师一直写的那种代码(尽管是在 VHDL 中),但它应该是可综合的。
OP 正在尝试设计某种参数化优先级编码器,如果我理解得很好的话。我带来了这个综合性很好的设计
module priority_encoder #(parameter WIDTH=4) (
input wire [WIDTH-1:0] i, // input data
input wire [WIDTH-1:0] c, // input control
output reg [WIDTH-1:0] o // output data
);
// Deal with the most significant bit case apart
always @* begin
if (c[WIDTH-1]==1'b1)
o[WIDTH-1] = i[WIDTH-1];
else
o[WIDTH-1] = 1'b0;
end
// Deal with the rest of bits
genvar idx;
generate
for (idx = WIDTH-2; idx >=0; idx = idx-1) begin :gen_cases
always @* begin
if (c[idx]==1'b1 && c[WIDTH-1:idx+1]=='b0)
o[idx] = i[idx];
else
o[idx] = 1'b0;
end
end
endgenerate
endmodule
我为此设计创建的测试台模块如下:
module tb_prioencoder;
parameter WIDTH=3;
// Inputs
reg [WIDTH-1:0] i;
reg [WIDTH-1:0] c;
// Outputs
wire [WIDTH-1:0] o;
// Instantiate the Unit Under Test (UUT)
priority_encoder #(WIDTH) uut (
.i(i),
.c(c[WIDTH-1:0]),
.o(o)
);
initial begin
i = {WIDTH{1'b1}};
c = {WIDTH{1'b0}};
repeat (2**WIDTH) begin
#10;
c = c + 1;
end
end
endmodule
这让我想到了这个时间表(WIDTH
= 3):
case 语句不能像那样被参数化。其他人提到的 for 循环是解决您的问题的好方法。
这是一个不同的解决方案:如果您要解决反向问题,即从右侧找到前导 1,您可以按位与 in
及其二进制补码。因此,要从左开始查找前导 1,可以先对 in
进行位取反,按位取其补码,然后对结果进行位取反:
logic [X - 1:0] reverse_in, reverse_out;
always_comb
begin
reverse_in = { << {in} }; //Bit-reverse of input (using stream operator)
reverse_out = (~(reverse_in) + 1) & reverse_in; //And with two's complement
out = { << {reverse_out} }; //Bit-reverse of output
end
在综合中,位反转没有任何成本,因为它只是重新布线。
我有一根叫做输入的电线,我想检测前导的数量 我正在尝试创建一个模块,该模块使用下面的 case 语句根据前导零的数量更改输出数据。但是输入的大小是可参数化的。
如果 X 是固定值 4,我会创建一个 case 语句,
case (input)
4'b0001 : o_data = {i_data[0]};
4'b001x : o_data = {i_data[1],1'b0};
4'b01xx : o_data = {i_data[2],2'b0};
4'b1xxx : o_data = {i_data[3],3'b0};
default : o_data = 4'b0000;
endcase
但是对于变量 X,我该如何定义所有情况?
这个问题与这个问题类似:How to define a parameterized multiplexer using SystemVerilog
你不能像那样真正参数化 case
语句,但你可以使用 for
循环代替:
module lead_detector #(parameter int WIDTH = 4) (
input logic[WIDTH - 1:0] in,
output logic[WIDTH - 1:0] out
);
always_comb begin
out = '0;
for (int i = WIDTH - 1; i >= 0; i--)
if (in[i] == 1'b1) begin
out[i] = 1;
break;
end
end
endmodule
这是我看到我的设计师一直写的那种代码(尽管是在 VHDL 中),但它应该是可综合的。
OP 正在尝试设计某种参数化优先级编码器,如果我理解得很好的话。我带来了这个综合性很好的设计
module priority_encoder #(parameter WIDTH=4) (
input wire [WIDTH-1:0] i, // input data
input wire [WIDTH-1:0] c, // input control
output reg [WIDTH-1:0] o // output data
);
// Deal with the most significant bit case apart
always @* begin
if (c[WIDTH-1]==1'b1)
o[WIDTH-1] = i[WIDTH-1];
else
o[WIDTH-1] = 1'b0;
end
// Deal with the rest of bits
genvar idx;
generate
for (idx = WIDTH-2; idx >=0; idx = idx-1) begin :gen_cases
always @* begin
if (c[idx]==1'b1 && c[WIDTH-1:idx+1]=='b0)
o[idx] = i[idx];
else
o[idx] = 1'b0;
end
end
endgenerate
endmodule
我为此设计创建的测试台模块如下:
module tb_prioencoder;
parameter WIDTH=3;
// Inputs
reg [WIDTH-1:0] i;
reg [WIDTH-1:0] c;
// Outputs
wire [WIDTH-1:0] o;
// Instantiate the Unit Under Test (UUT)
priority_encoder #(WIDTH) uut (
.i(i),
.c(c[WIDTH-1:0]),
.o(o)
);
initial begin
i = {WIDTH{1'b1}};
c = {WIDTH{1'b0}};
repeat (2**WIDTH) begin
#10;
c = c + 1;
end
end
endmodule
这让我想到了这个时间表(WIDTH
= 3):
case 语句不能像那样被参数化。其他人提到的 for 循环是解决您的问题的好方法。
这是一个不同的解决方案:如果您要解决反向问题,即从右侧找到前导 1,您可以按位与 in
及其二进制补码。因此,要从左开始查找前导 1,可以先对 in
进行位取反,按位取其补码,然后对结果进行位取反:
logic [X - 1:0] reverse_in, reverse_out;
always_comb
begin
reverse_in = { << {in} }; //Bit-reverse of input (using stream operator)
reverse_out = (~(reverse_in) + 1) & reverse_in; //And with two's complement
out = { << {reverse_out} }; //Bit-reverse of output
end
在综合中,位反转没有任何成本,因为它只是重新布线。