问题:在对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