一些基本背景:我有一个显示驱动程序,需要处理一些输入并将结果显示在分段显示器上。 通过在“ statusDisplay”中设置数值来更新分段显示。 我已将此代码简化为仅显示驱动程序,并试图显示一个简单的计数器。

使用分段显示很令人兴奋,但是可以。 但是,一旦我尝试在statusDisplay寄存器中输入一个值,Vivado就会说存在一个组合反馈循环。 对于我的一生,我不知道为什么或如何解决它。

我什至创建了一些测试代码,它们基本上完成了相同的操作,并且不会导致任何问题。

奇怪的是,还编译器报告线路上的问题“ticker1 <= ticker1 + 1”,但仅除去“线valueToDisplay <= bigCounter”解决问题。

谢谢!!!

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

#1楼 票数:2 已采纳

我猜您跳过了模拟,直接进入了综合。 always @(clk)应该always @(posedge clk)

与模拟器不同,合成器并不严格遵循灵敏度列表。 合成器寻找关键字posedgenegedge来确定逻辑是否应该是同步的(然后其他步骤确定它是否是异步控制)。 否则,它假定是异步的。

ticker1 <= ticker1+1 ,合成器将忽略选择性列表,然后将ticker1 <= ticker1+1视为反馈循环。 删除statusDisplay <= ticker1 + 1 sudo可解决此问题,因为在其他任何地方都未引用ticker1 ,因此已对其进行了优化。

always @(posedge clk)
begin
    ticker1 <= ticker1 + 1;
    if( (ticker1 & 32'h7FFF) == 32'h7FFF )
        statusDisplay <= ticker1 + 1;
end

  ask by vositis translate from so

未解决问题?本站智能推荐:

2回复

Vivado 2016.1:综合后,它将删除有用的逻辑。 Verilog

我目前正在构建软核处理器,并且在合成Verilog实现的RAM和其他顺序元素时遇到了麻烦。 我决定在处理器的每个部分上单独工作,以便找出正在发生的事情,但恐怕还没有运气。 我尝试合成的电路主要做两件事:用时钟驱动的数据填充内存; 在存储器中充满数据之后,一个标志将指示向外部处理器发送信号,
1回复

组合verilog

使用子模块(encrypt_system)的输出数据成为新子模态的输入时,我遇到了问题。 以前,我已经在系统中成功生成了228位二进制文​​件(称为secret_key)。 但是,当我尝试将此secret_Key用作新子模块的输入时,模拟显示没有生成任何数据。 我不知道这是什么问题。
1回复

在Vivado + Verilog中创建多端口块ram

我想在我的FPGA中进行卷积。 我确实有一个数组,用于存储图像,然后通过VGA将其输出到屏幕。 我想在像素被移出时计算卷积,这样我只需要乘以卷积内核的大小即可。 但是,我不知道如何创建一个块内存,这样我就可以同时访问9个地址(如果我使用的是3x3卷积内核)。 在Vivado中有可能吗
1回复

verilog线性反馈移位寄存器随机

我使用QuartusII编写verilog编程代码。 我想进行随机数生成操作。 线性反馈移位寄存器用于生成随机数。 但是,我不知道为什么随机模式相同。 这样的运算结果8 5 4 2 7 .... 8 5 4 2 7.如何解决这些问题? 请参考您的意见。
1回复

Verilog如何展开嵌套循环?

我正在尝试使用一系列嵌套的for循环来进行累加,并且没有运气。 我想我需要对Verilog如何展开for循环有更好的了解,然后才能真正形象地看到如何解决问题。 本质上,我有一系列的Tap输出(tap_output_i和tap_output_q),它们是3D数组(src,dst,tap)。
2回复

vivado块设计器在修改verilog或vhdl RTL文件后未更新块设计中的RTL接口

我发誓vivado有一个错误,就是在将其粘贴到带有“添加模块”的“块设计”中之后,它永远不会刷新对RTL文件,verilog或vhdl所做的任何接口更改。 让Vivado块设计者看到对导入到“块设计”中的verilog或vhdl文件的接口所做的文件更改,有什么秘诀? 然后,您尝试通过
4回复

为什么If语句会导致verilog中的锁存?

我试图在Verilog中编写控制器/数据路径实现,我很困惑什么会导致不必要的锁存器。 基本上,我有一个状态机更新negedge时钟。 该状态机根据机器所处的状态向数据路径发送5个控制信号(loadSquare,loadDelta,addDelta等)。数据路径和控制器的代码如下所示。
3回复

如果语句在Verilog中导致闩锁推断?

我正在编写用于算法综合的Verilog代码,我对可能导致锁存器推断的情况有些困惑。 下面是代码的此类部分,尽管它在模拟中可以正常工作,但我担心它可能会在硬件上引起问题。 因此,在这种情况下,我只希望数据在指定限制内​​进行映射。 是否会因为未定义“其他”方案而推断出闩锁? 我没有添