[英]Can someone please explain why this causes a combinational feedback loop? (Vivado Verilog)
Some basic background: I have a display driver and need to process some inputs and display the results on the segmented display.一些基本背景:我有一个显示驱动程序,需要处理一些输入并将结果显示在分段显示器上。 The segmented display is updated by setting a numeric value in 'statusDisplay'.
通过在“statusDisplay”中设置数值来更新分段显示。 I have simplified this code to just the display driver and trying to display a simple counter.
我已将此代码简化为仅显示驱动程序并尝试显示一个简单的计数器。
Using the segmented display is exciting, but it works.使用分段显示令人兴奋,但它确实有效。 But as soon as I try to put a value in the statusDisplay register Vivado says there is a combinational feedback loop.
但是一旦我尝试在 statusDisplay 寄存器中输入一个值,Vivado 就会说有一个组合反馈循环。 For the life of me, I can't figure out why or how to fix it.
对于我的生活,我无法弄清楚为什么或如何解决它。
I even created some test code that essentially does the same thing and it doesn't result in a problem.我什至创建了一些测试代码,它们基本上做同样的事情并且不会导致问题。
Oddly, also the compiler reports the problem on the line 'ticker1 <= ticker1+1', but only removing the line 'valueToDisplay <= bigCounter' solves the problem.奇怪的是,编译器也在“ticker1 <=ticker1+1”行上报告了问题,但只有删除“valueToDisplay <= bigCounter”行才能解决问题。
Thank you!!!谢谢!!!
timescale 1ns / 1ps
module circuit1_top(
input clk,
output [15:0] LED, // Create two outputs
output [7:0] SSEG_CA,
output [7:0] SSEG_AN
);
reg [31:0] counter = 32'h0;
reg [0:0] divclk = 1'b0;
reg [0:0] showclk= 1'b0;
reg [15:0] caseCounter = 15'b0;
reg [15:0] LedReg=0;
reg [7:0] SegReg;
reg [7:0] DigReg;
reg [31:0] Hex = 0;
reg [0:0] segclk = 1'b0, scroll = 1'b0;
reg [31:0] displayNumber;
reg [2:0] segNumber = 3'b0;
reg [31:0] statusDisplay;
reg [31:0] display1, display2, display3, display4, display5, display6, display7, display8, display9, display10;
reg [31:0] ticker1=0;
initial
begin
scroll = 0;
displayNumber = 32'hDEADBEEF;
statusDisplay = 32'h80085;
display1=1;
display2=2;
display3=3;
display4=4;
display5=5;
display6=6;
display7=7;
display8=8;
display9=9;
display10=10;
end
// Testing simpler similar code - this does not create a loop problem
reg [31:0] bigCounter=0;
reg [31:0] valueToDisplay=0;
reg [31:0] displayRegister=0;
always @(clk)
begin
bigCounter <= bigCounter + 1;
if( (bigCounter & 32'h7FFF) == 32'h7FFF )
valueToDisplay <= bigCounter;
end
always @(clk)
begin
displayRegister <= valueToDisplay;
end
// End Test Code
always @(clk)
begin
ticker1 <= ticker1 + 1; //. <<—- This line is reported as causing the problem
if( (ticker1 & 32'h7FFF) == 32'h7FFF )
statusDisplay <= ticker1 + 1; // <<—- Removing this line actually solves the problem
end
// Display driver starts here...
// Retrieve display segments based on number to display
task automatic getSegments;
input [7:0] number;
output [7:0] segment_ca;
begin
case (number)
4'h0 :segment_ca <= 8'b11000000; // 0
4'h1 :segment_ca <= 8'b11111001; // 1
4'h2 :segment_ca <= 8'b10100100; // 2
4'h3 :segment_ca <= 8'b10110000; // 3
4'h4 :segment_ca <= 8'b10011001; // 4
4'h5 :segment_ca <= 8'b10010010; // 5
4'h6 :segment_ca <= 8'b10000010; // 6
4'h7 :segment_ca <= 8'b11111000; // 7
4'h8 :segment_ca <= 8'b10000000; // 8
4'h9 :segment_ca <= 8'b10010000; // 9
4'hA :segment_ca <= 8'b10001000; // A
4'hB :segment_ca <= 8'b10000011; // b
4'hC :segment_ca <= 8'b11000110; // C
4'hD :segment_ca <= 8'b10100001; // d
4'hE :segment_ca <= 8'b10000110; // E
4'hF :segment_ca <= 8'b10001110; // F
default: begin end
endcase
end
endtask
assign SSEG_AN = DigReg;
assign SSEG_CA = SegReg;
always @(posedge segclk)
segNumber <= segNumber + 1;
always @(posedge segclk)
begin
case( segNumber )
4'h0: begin DigReg <= ~(32'h1); getSegments( displayNumber & 4'b1111, SegReg ); end
4'h1: begin DigReg <= ~(((displayNumber < 32'h10 ? 1'b0 : 1'b1) & 32'h1) << 1); getSegments( (displayNumber>>4) & 4'b1111, SegReg ); end
4'h2: begin DigReg <= ~(((displayNumber < 32'h100 ? 1'b0 : 1'b1) & 32'h1) << 2); getSegments( (displayNumber>>8) & 4'b1111, SegReg ); end
4'h3: begin DigReg <= ~(((displayNumber < 32'h1000 ? 1'b0 : 1'b1) & 32'h1) << 3); getSegments( (displayNumber>>12) & 4'b1111, SegReg ); end
4'h4: begin DigReg <= ~(((displayNumber < 32'h10000 ? 1'h0 : 1'h1) & 32'h1) << 4); getSegments( (displayNumber>>16) & 4'b1111, SegReg ); end
4'h5: begin DigReg <= ~(((displayNumber < 32'h100000 ? 1'h0 : 1'h1) & 32'h1) << 5); getSegments( (displayNumber>>20) & 4'b1111, SegReg ); end
4'h6: begin DigReg <= ~(((displayNumber < 32'h1000000 ? 1'h0 : 1'h1) & 32'h1) << 6); getSegments( (displayNumber>>24) & 4'b1111, SegReg ); end
4'h7: begin DigReg <= ~(((displayNumber < 32'h10000000 ? 1'h0 : 1'h1) & 32'h1) << 7); getSegments( (displayNumber>>28) & 4'b1111, SegReg ); end
default: begin end
endcase
end
////clock divider////
always @(posedge clk)
begin
if( (counter & 16'h7FFF) == 16'h7FFF ) begin
segclk <= ~segclk; // Switch to the next segment in the display
end
if(counter == 32'h17D7840) begin // 1/4 second, so change every 1/2 second...
counter <= 32'h0; // This only really matters if we are scrolling divclk <= ~divclk;
end
else begin
counter <= counter + 1'b1;
end
end
always @(posedge divclk)
begin
if(caseCounter == 9) begin // Over it!!
caseCounter <= 0;
end
else begin
caseCounter <= caseCounter + 1'b1;
end
end
always @(posedge divclk)
begin
if( scroll ) // Scroll through ten potential outputs display
begin
case( caseCounter )
0: displayNumber <= display1;
1: displayNumber <= display2;
2: displayNumber <= display3;
3: displayNumber <= display4;
4: displayNumber <= display5;
5: displayNumber <= display6;
6: displayNumber <= display7;
7: displayNumber <= display8;
8: displayNumber <= display9;
9: displayNumber <= display10;
default ;
endcase
LedReg <= 1 << caseCounter;
end
else
displayNumber <= statusDisplay; // This is the only access to statusDisplay
end
assign LED = LedReg;
endmodule
I'm guessing you skipped simulation and went straight to synthesis.我猜你跳过模拟直接进入合成。
always @(clk)
should be always @(posedge clk)
always @(clk)
应该always @(posedge clk)
Unlike simulators, synthesizers do not strictly follow the sensitivity list.与模拟器不同,合成器并不严格遵循灵敏度列表。 Synthesizers look for the keywords
posedge
and negedge
to decide if the logic should be a synchronous (then other steps to determine if it is asynchronous control).合成器查找关键字
posedge
和negedge
来决定逻辑是否应该是同步的(然后是其他步骤来确定它是否是异步控制)。 Otherwise it assumes asynchronous.否则它假定是异步的。
As is, the synthesizers will ignore the selectivity list then see ticker1 <= ticker1+1
as a feedback loop.照原样,合成器将忽略选择性列表,然后将
ticker1 <= ticker1+1
视为反馈循环。 Removing the statusDisplay <= ticker1 + 1
sudo solves the problem because ticker1
is not referenced anywhere else and therefore it is optimized out.删除
statusDisplay <= ticker1 + 1
sudo 解决了这个问题,因为ticker1
在其他任何地方都没有被引用,因此它被优化了。
always @(posedge clk)
begin
ticker1 <= ticker1 + 1;
if( (ticker1 & 32'h7FFF) == 32'h7FFF )
statusDisplay <= ticker1 + 1;
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.