如何在参数化设计中使用组合逻辑分配输出

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