xilinx vivado的Combinatorial Loop Alert

问题:在对inout信号进行处理的工程中,生成bit文件的过程中遇到的组合逻辑循环报警的错误,这里需要的xdc中添加必要的约束才能解决,具体软件报错如下:

[DRC 23-20] Rule violation (LUTLP-1) Combinatorial Loop Alert - 3 LUT cells form a combinatorial loop. This can create a race condition. Timing analysis may not be accurate. The preferred resolution is to modify the design to remove combinatorial logic loops. If the loop is known and understood, this DRC can be bypassed by acknowledging the condition and setting the following XDC constraint on any net in the loop: 'set_property ALLOW_COMBINATORIAL_LOOPS TRUE [net_nets <myHier/myNet>'. The cells in the loop are: design_1_i/k115_GPIO_0/inst/k115_pin[0]_INST_0, design_1_i/k115_GPIO_0/inst/zynq_pin[0]_INST_0, design_1_i/k115_GPIO_0/inst/zynq_pin[0]_INST_0_i_1.

解决:

再xdc中添加如下的约束:

set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets -of_objects [get_cells design_1_i/k115_GPIO_0/inst/k115_pin[*]_INST_0]]
set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets -of_objects [get_cells design_1_i/k115_GPIO_0/inst/zynq_pin[*]_INST_0]]
set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets -of_objects [get_cells design_1_i/k115_GPIO_0/inst/zynq_pin[*]_INST_0_i_1]]

set_property SEVERITY {Warning}  [get_drc_checks LUTLP-1]

set_property SEVERITY {Warning} [get_drc_checks NSTD-1]

问题参考链接:

https://forums.xilinx.com/xlnx/board/crawl_message?board.id=IMPBD&message.id=18353

verilog代码:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: hypersilicon   
// Engineer: ryanyan
//
// Create Date: 2018/07/16 12:29:15
// Design Name: k115_gpio
// Module Name: k115_GPIO
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module k115_GPIO(
inout  [9:0]  zynq_pin,
inout  [9:0]  k115_pin,

input         sys_clk,//50~100Mhz
///////////bram port/////////////
input              bram_en,
input       [3:0]  bram_we,
input       [16:0] bram_adder,
input              bram_clk,
input              bram_rst,  
input       [31:0] bram_wr_data,
output  reg [31:0]  bram_rd_data
);

/************************register**************************88*/
reg  [31:0]  reg_ctl;// adder=0;2n bits define in/out,2n+1 bits define k115/zynq
                     //in=0,out=1
                     //k115=0,zynq=1
reg  [31:0]  reg_wr; // adder=1;defines the value which is written to the register in zynq,when the pin is out
reg  [31:0]  reg_rd; // adder=2;the value of the input value ,when the pin is in and the fpga is zynq
reg  [31:0]  reg_msk; //adder=3;
                      //bit[n]=1:mask is enable;
                      //bit[n]=0:normal operation
wire    [9:0]  net_in;
wire    [9:0]  net_out;


//    wire  [9:0]       zynq_pin;
//    wire  [9:0]       k115_pin;
    wire   [9:0]       zynq_pin_reg;
    wire   [9:0]       k115_pin_reg;
    wire   [9:0]       zynq_pin_oe;//oe=1,output
    wire   [9:0]       k115_pin_oe;
    
    assign zynq_pin=zynq_pin_oe?zynq_pin_reg:10'bz;
    assign k115_pin=k115_pin_oe?k115_pin_reg:10'bz;
    
    
////////////////////reg_msk///////////////////////
always @(posedge bram_clk or posedge bram_rst)
begin
 if(bram_rst==1'b1)
   reg_msk<=32'hFFFFF;
 else if((bram_en==1'b1)&&(bram_we==4'b1111)&&(bram_adder==17'h3))
   reg_msk<=bram_wr_data;
 else if((bram_en==1'b1)&&(bram_we==4'b1111)&&(bram_adder!=17'h3))
   reg_msk<=32'hFFFFF;
 else
   reg_msk<=reg_msk;
end
////////////////////reg_ctrl///////////////////////
genvar i;
generate
 for (i=0;i<=19;i=i+1) begin :operation_ctrl
    always @(posedge bram_clk or posedge bram_rst)
        begin
          if(bram_rst==1'b1)
             reg_ctl[i]<=1'b0;
          else if((bram_en==1'b1) && (bram_we==4'b1111) && (bram_adder==17'h0) && (reg_msk[i]==1'b0))
             reg_ctl[i]<=bram_wr_data[i];
          else
             reg_ctl[i]<=reg_ctl[i];
        end
        end
endgenerate
////////////////////reg_wr///////////////////////
genvar h;
generate
 for (h=0;h<=19;h=h+1) begin :operation_write
    always @(posedge bram_clk or posedge bram_rst)
        begin
          if(bram_rst==1'b1)
             reg_wr[h]<=1'b0;
          else if((bram_en==1'b1) && (bram_we==4'b1111) && (bram_adder==17'h1) && (reg_msk[h]==1'b0))
             reg_wr[h]<=bram_wr_data[h];
          else
             reg_wr[h]<=reg_wr[h];
        end
        end
endgenerate

////////////////////reg_rd///////////////////////
always @(posedge bram_clk or posedge bram_rst)
begin
 if(bram_rst==1'b1)
   bram_rd_data<=32'b0;
 else if((bram_en==1'b1)&&(bram_we==4'b0000)&&(bram_adder==17'h2))
   bram_rd_data<=reg_rd;
 else
   bram_rd_data<=bram_rd_data;
end


/*******************net operation*********************/
//net_in=(in1 or out0) ? zynq_pin : 1'bz;            
//pin_k115=(K115_1 or zynq_0) ? net_in : 1'bz                
//reg_zynq_read=(K115_1 or zynq_0) ? 1'bz :  net_in

//    zynq_pin=(in0 or out1)1'bz :net_out            
//  net_out=(K115_0 or zynq_1) ? Pin_k115 : reg_zynq_write;                    
wire [9:0]     net_in_1;        
genvar j;
generate
for(j=0;j<=9;j=j+1) begin:net_op
     //////////in///////////
   assign net_in[j]=reg_ctl[2*j]?1'bz:zynq_pin[j];
   assign k115_pin_reg[j]=reg_ctl[2*j+1]?1'bz:net_in[j];
   //assign net_in_1[j]=reg_ctl[2*j+1]?net_in[j]:1'bz;
   always @(posedge sys_clk or posedge bram_rst)
      begin
         if(bram_rst==1'b1)
          reg_rd[2*j+1:2*j]<=2'b0;
         else if(reg_ctl[2*j+1:2*j]==2'b10)
          reg_rd[2*j+1:2*j]<={1'b1,net_in[j]};
         else
          reg_rd[2*j+1:2*j]<={1'b0,1'bz};
      end
     //////////////out///////////////
   assign zynq_pin_reg[j]=reg_ctl[2*j]?net_out[j]:1'bz;
   assign net_out[j]=reg_ctl[2*j+1]? reg_wr[2*j]:k115_pin[j];
   
   assign zynq_pin_oe[j]=reg_ctl[2*j];
   assign k115_pin_oe[j]=~reg_ctl[2*j];
   end
endgenerate

endmodule

猜你喜欢

转载自blog.csdn.net/suixintt/article/details/81281969