如何在参数化设计中使用组合逻辑分配输出
How to assign an output with combinational logic on a parametric design
我想实现一个多路复用器,给定控制信号 (addr_i) 将寄存器 (slv_reg[i]) 的内容输入到输出 (data_o) .其中 "i" 是从 0 到模块参数 TOTAL_REGS 的值。
我可以在不生成锁存器的情况下在 for 循环中分配 slv_reg 吗?
我写了几个简单的例子。但是,即使我的逻辑涵盖了所有可能的条件,如果缺少 else,它也会生成一个锁存器。手动做的时候,我可以写else,问题就解决了,但是用循环的时候,我就不知道怎么办了。
module why_latch_1 #
(
// Width of data bus
parameter integer DATA_WIDTH = 32,
// Number of registers
parameter integer TOTAL_REGS = 3
)
(
input wire clk_i,
input wire rstn_i,
input wire [DATA_WIDTH-1:0] addr_i,
output wire [DATA_WIDTH-1:0] data_o
);
reg [DATA_WIDTH-1:0] slv_reg [0:TOTAL_REGS-1];
reg [DATA_WIDTH-1:0] reg_data_out;
assign data_o = reg_data_out;
integer i;
always @(posedge clk_i)
if (~rstn_i) begin
for (i=0; i<TOTAL_REGS; i=i+1) begin
slv_reg[i]<={DATA_WIDTH{1'b0}};
end
end
always_comb
begin : decode
//check if the address is out of the range of R registers
if (addr_i>0 && addr_i <= TOTAL_REGS) begin
//this is a latch
integer i;
for(i=0;i<TOTAL_REGS;i++)begin
if(addr_i==i) begin
reg_data_out =slv_reg[i];
end
end
end else
reg_data_out ={DATA_WIDTH{1'b0}};
end
endmodule
module why_latch_2 #
(
// Width of data bus
parameter integer DATA_WIDTH = 32,
// Number of registers
parameter integer TOTAL_REGS = 3
)
(
input wire clk_i,
input wire rstn_i,
input wire [DATA_WIDTH-1:0] addr_i,
output wire [DATA_WIDTH-1:0] data_o
);
reg [DATA_WIDTH-1:0] slv_reg [0:TOTAL_REGS-1];
reg [DATA_WIDTH-1:0] reg_data_out;
assign data_o = reg_data_out;
integer i;
always @(posedge clk_i)
if (~rstn_i) begin
for (i=0; i<TOTAL_REGS; i=i+1) begin
slv_reg[i]<={DATA_WIDTH{1'b0}};
end
end
always_comb
begin : decode
//check if the address is out of the range of R registers
if (addr_i>0 && addr_i <= TOTAL_REGS) begin
//this is NOT a latch
if(addr_i==0)
reg_data_out =slv_reg[0];
else
if(addr_i==1)
reg_data_out =slv_reg[1];
else
reg_data_out =slv_reg[2];
end else
reg_data_out ={DATA_WIDTH{1'b0}};
end
endmodule
通过使用 spyglass 作为 linting 工具,我得到了以下报告:
对于模块 why_latch_2。一切都很好,如我所料。
############### BuiltIn -> RuleGroup=Design Read ###############
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ID Rule Alias Severity File Line Wt Message
======================================================================================
[1] DetectTopDesignUnits DetectTopDesignUnits Info ./why_latch_2.sv 1 2 Module why_latch_2 is a top level desi
gn unit
[0] ElabSummary ElabSummary Info ./why_latch_2/why_latch_2/lint/lint_rtl/spyglass_reports/SpyGlass/elab_summary.rpt 0 2 Please refer file './why_latch_2/why_l
atch_2/lint/lint_rtl/spyglass_reports/SpyGlass/elab_summary.rpt' for elab summary report
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
对于why_latch_1:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MORESIMPLE REPORT:
############### BuiltIn -> RuleGroup=Design Read ###############
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ID Rule Alias Severity File Line Wt Message
======================================================================================
[1] DetectTopDesignUnits DetectTopDesignUnits Info ./why_latch_1.sv 1 2 Module why_latch_1 is a top
level design unit
[4] SYNTH_12608 SynthesisWarning ./why_latch_1.sv 27 1000 why_latch_1 -> The logic of
the always block mismatches with the type of Always Block(which should be "always_latch (Latch)") due to latch instance \reg_data_out_reg[0]
[0] ElabSummary ElabSummary Info ./why_latch_1/why_latch_1/lint/lint_rtl/spyglass_reports/SpyGlass/elab_summary.rpt 0 2 Please refer file './why_lat
ch_1/why_latch_1/lint/lint_rtl/spyglass_reports/SpyGlass/elab_summary.rpt' for elab summary report
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
############### Non-BuiltIn -> Goal=lint/lint_rtl ###############
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ID Rule Alias Severity File Line Wt Message
======================================================================================
[7] InferLatch (OpenMORE 5.5.2.1) Error ./why_latch_1.sv 40 5 Latch inferred for signal 'reg_data_out[31:0]' in module 'why_latch_1'
[2] W415a Warning ./why_latch_1.sv 35 5 Signal reg_data_out is being assigned multiple times ( assignment within same for-loop ) in same always block [Hiera
rchy: ':why_latch_1']
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
这应该会在您的案例中生成闩锁。您并未在此处涵盖所有可能的情况。
for(i=0;i<TOTAL_REGS;i++)begin
if(addr_i==i) begin
reg_data_out =slv_reg[i];
end
end
试试这个。提前移动默认案例:
begin : decode
//check if the address is out of the range of R registers
reg_data_out ='0; // do default assignment before the rest
if (addr_i>0 && addr_i <= TOTAL_REGS) begin
//this is a latch
integer i;
for(i=0;i<TOTAL_REGS;i++)begin
if(addr_i==i) begin
reg_data_out =slv_reg[i];
end
end
end
end
我想实现一个多路复用器,给定控制信号 (addr_i) 将寄存器 (slv_reg[i]) 的内容输入到输出 (data_o) .其中 "i" 是从 0 到模块参数 TOTAL_REGS 的值。 我可以在不生成锁存器的情况下在 for 循环中分配 slv_reg 吗?
我写了几个简单的例子。但是,即使我的逻辑涵盖了所有可能的条件,如果缺少 else,它也会生成一个锁存器。手动做的时候,我可以写else,问题就解决了,但是用循环的时候,我就不知道怎么办了。
module why_latch_1 #
(
// Width of data bus
parameter integer DATA_WIDTH = 32,
// Number of registers
parameter integer TOTAL_REGS = 3
)
(
input wire clk_i,
input wire rstn_i,
input wire [DATA_WIDTH-1:0] addr_i,
output wire [DATA_WIDTH-1:0] data_o
);
reg [DATA_WIDTH-1:0] slv_reg [0:TOTAL_REGS-1];
reg [DATA_WIDTH-1:0] reg_data_out;
assign data_o = reg_data_out;
integer i;
always @(posedge clk_i)
if (~rstn_i) begin
for (i=0; i<TOTAL_REGS; i=i+1) begin
slv_reg[i]<={DATA_WIDTH{1'b0}};
end
end
always_comb
begin : decode
//check if the address is out of the range of R registers
if (addr_i>0 && addr_i <= TOTAL_REGS) begin
//this is a latch
integer i;
for(i=0;i<TOTAL_REGS;i++)begin
if(addr_i==i) begin
reg_data_out =slv_reg[i];
end
end
end else
reg_data_out ={DATA_WIDTH{1'b0}};
end
endmodule
module why_latch_2 #
(
// Width of data bus
parameter integer DATA_WIDTH = 32,
// Number of registers
parameter integer TOTAL_REGS = 3
)
(
input wire clk_i,
input wire rstn_i,
input wire [DATA_WIDTH-1:0] addr_i,
output wire [DATA_WIDTH-1:0] data_o
);
reg [DATA_WIDTH-1:0] slv_reg [0:TOTAL_REGS-1];
reg [DATA_WIDTH-1:0] reg_data_out;
assign data_o = reg_data_out;
integer i;
always @(posedge clk_i)
if (~rstn_i) begin
for (i=0; i<TOTAL_REGS; i=i+1) begin
slv_reg[i]<={DATA_WIDTH{1'b0}};
end
end
always_comb
begin : decode
//check if the address is out of the range of R registers
if (addr_i>0 && addr_i <= TOTAL_REGS) begin
//this is NOT a latch
if(addr_i==0)
reg_data_out =slv_reg[0];
else
if(addr_i==1)
reg_data_out =slv_reg[1];
else
reg_data_out =slv_reg[2];
end else
reg_data_out ={DATA_WIDTH{1'b0}};
end
endmodule
通过使用 spyglass 作为 linting 工具,我得到了以下报告:
对于模块 why_latch_2。一切都很好,如我所料。
############### BuiltIn -> RuleGroup=Design Read ###############
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ID Rule Alias Severity File Line Wt Message
======================================================================================
[1] DetectTopDesignUnits DetectTopDesignUnits Info ./why_latch_2.sv 1 2 Module why_latch_2 is a top level desi
gn unit
[0] ElabSummary ElabSummary Info ./why_latch_2/why_latch_2/lint/lint_rtl/spyglass_reports/SpyGlass/elab_summary.rpt 0 2 Please refer file './why_latch_2/why_l
atch_2/lint/lint_rtl/spyglass_reports/SpyGlass/elab_summary.rpt' for elab summary report
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
对于why_latch_1:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MORESIMPLE REPORT:
############### BuiltIn -> RuleGroup=Design Read ###############
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ID Rule Alias Severity File Line Wt Message
======================================================================================
[1] DetectTopDesignUnits DetectTopDesignUnits Info ./why_latch_1.sv 1 2 Module why_latch_1 is a top
level design unit
[4] SYNTH_12608 SynthesisWarning ./why_latch_1.sv 27 1000 why_latch_1 -> The logic of
the always block mismatches with the type of Always Block(which should be "always_latch (Latch)") due to latch instance \reg_data_out_reg[0]
[0] ElabSummary ElabSummary Info ./why_latch_1/why_latch_1/lint/lint_rtl/spyglass_reports/SpyGlass/elab_summary.rpt 0 2 Please refer file './why_lat
ch_1/why_latch_1/lint/lint_rtl/spyglass_reports/SpyGlass/elab_summary.rpt' for elab summary report
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
############### Non-BuiltIn -> Goal=lint/lint_rtl ###############
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ID Rule Alias Severity File Line Wt Message
======================================================================================
[7] InferLatch (OpenMORE 5.5.2.1) Error ./why_latch_1.sv 40 5 Latch inferred for signal 'reg_data_out[31:0]' in module 'why_latch_1'
[2] W415a Warning ./why_latch_1.sv 35 5 Signal reg_data_out is being assigned multiple times ( assignment within same for-loop ) in same always block [Hiera
rchy: ':why_latch_1']
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
这应该会在您的案例中生成闩锁。您并未在此处涵盖所有可能的情况。
for(i=0;i<TOTAL_REGS;i++)begin
if(addr_i==i) begin
reg_data_out =slv_reg[i];
end
end
试试这个。提前移动默认案例:
begin : decode
//check if the address is out of the range of R registers
reg_data_out ='0; // do default assignment before the rest
if (addr_i>0 && addr_i <= TOTAL_REGS) begin
//this is a latch
integer i;
for(i=0;i<TOTAL_REGS;i++)begin
if(addr_i==i) begin
reg_data_out =slv_reg[i];
end
end
end
end