Некоторый базовый фон: у меня есть драйвер дисплея, и мне нужно обработать некоторые входные данные и отобразить результаты на сегментированном дисплее.Сегментированный дисплей обновляется путем установки числового значения в «statusDisplay».Я упростил этот код до драйвера дисплея и пытался отобразить простой счетчик.
Использование сегментированного дисплея интересно, но оно работает.Но как только я пытаюсь поместить значение в регистр statusDisplay, Вивадо говорит, что существует комбинационная петля обратной связи.Что касается жизни, я не могу понять, почему или как это исправить.
Я даже создал некоторый тестовый код, который по сути делает то же самое, и это не приводит к проблеме.
Как ни странно, также компилятор сообщает о проблеме в строке 'ticker1 <= ticker1 + 1', но только удаление строки 'valueToDisplay <= bigCounter' решает проблему. </p>
Спасибо!!!
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