0
\$\begingroup\$

I'm currently trying to implement a FPGA design using a 325 MHz clock, which writes to the SDRAM Controller of a Cyclone V 5CSEBA6U23I7 (Speed Grade 7).
When running my IP Core with 2 MHz everything works fine, but when I change the PLL clock to either 200 MHz or 325 MHz the data I can observe with SignalTap becomes completly random.
I've attached an image, in which I want to point out the 4th signal (bRun), which should be constant at 1, but in the observation toggles to 0 and back to 1. Some other signals also experience completly random behaviour, like some internal busses, which carry non-zero data, when they should be zero.
I don't think this is an EMC problem, because I'm using a development board (DE10-Nano from terasic) and all signals are FPGA-internal, which should be able to handle these clockspeeds.
enter image description here The IP-Core is written in Verilog and I made sure to synchronize read and write operations on different edges of the respective clock to make sure, that the signals are stable and not transitioning when being read.
Following you can find the code for my RAM-write state machine, but as stated it works perfectly fine at 2 MHz.
If you guys have any idea about the reason for this behaviour I'd be very thankful.

always@(posedge clock_clk_ram or posedge reset_reset)
begin
    if(reset_reset)
    begin
        imgSize <= 32'b0;
        nCntCurPos <= 4'b0;
        nOutWord <= 256'b0;
        irqFromFPGAMaster <= 0;
        state <= 3'b0;

        fifo_read <= 0;

        avm_m0_address <= 27'b0;
        avm_m0_writedata <= 256'b0;
        avm_m0_write <= 0;
        avm_m0_byteenable <= 32'b0;
    end
    else
    begin
        if(clearIrqFromHPS||~bRun)//reset all states after irq has been handled, or if device has been stopped
        begin
            imgSize <= 32'b0;
            nCntCurPos <= 4'b0;
            nOutWord <= 256'b0;
            irqFromFPGAMaster <= 0;
            state <= 3'b0;

            fifo_read <= 0;

            avm_m0_address <= 27'b0;
            avm_m0_writedata <= 256'b0;
            avm_m0_write <= 0;
            avm_m0_byteenable <= 32'b0;
        end
        else if(bRun && ~irqFromFPGAMaster && ~clearIrqFromHPS)//RAM access okay
        begin
            case(state) 
                'b000://accumulate 256 bit data
                begin
                    if(~fifo_empty)// && fifo_rnuminfifo!='b0001)
                    begin
                        imgSize <= imgSize + 'd2;//is going to be incremented in the next cycle (d-flipflop)
                        nCntCurPos <= nCntCurPos + 4'b1;//is going to be incremented in the next cycle (d-flipflop)
                        fifo_read <= 1;
                        irqFromFPGAMaster <= 0;
                        avm_m0_address <= 27'b0;
                        avm_m0_writedata <= 256'b0;
                        avm_m0_write <= 0;

                        nOutWord[nCntCurPos*16 +: 16] <= fifo_out;
                        avm_m0_byteenable[nCntCurPos*2 +: 2] <= 2'b11;

                        if(imgSize >= maxImgSize - 32'd2)   //image done, transmit data and fire irq
                            state <= 3'b101;
                        else if(nCntCurPos=='d15)       //process transfer without irq
                            state <= 3'b001;
                        else                                    //else continue to accumulate data
                            state <= 3'b000;
                    end
                    else//FIFO is empty, wait for more data
                    begin
                        imgSize <= imgSize;
                        nCntCurPos <= nCntCurPos;
                        nOutWord <= nOutWord;
                        irqFromFPGAMaster <= 0;
                        state <= 3'b000;

                        fifo_read <= 0;

                        avm_m0_address <= 27'b0;
                        avm_m0_writedata <= 256'b0;
                        avm_m0_write <= 0;
                        avm_m0_byteenable <= avm_m0_byteenable;
                    end
                end
                'b001,//write to sdram, after that accumulate more data
                'b101://write to sdram, after that trigger interrupt
                begin
                    imgSize <= imgSize;
                    nCntCurPos <= 4'b0;
                    nOutWord <= nOutWord;
                    irqFromFPGAMaster <= 0;
                    fifo_read <= 0;
                    if(imgSize>32)  avm_m0_address <= baseAddress+((imgSize>>5)-27'd1);
                    else                avm_m0_address <= baseAddress;
                    avm_m0_writedata <= nOutWord;
                    avm_m0_write <= 1;
                    avm_m0_byteenable <= avm_m0_byteenable;
                    if(~avm_m0_waitrequest) state <= state ^ 3'b011;
                    else                            state <= state;
                end
                'b010,//end of single transmit
                'b110://end of img, 
                begin
                    imgSize <= imgSize;
                    nCntCurPos <= 4'b0;
                    nOutWord <= 256'b0;

                    fifo_read <= 0;

                    avm_m0_address <= 27'b0;
                    avm_m0_writedata <= 256'b0;
                    avm_m0_write <= 0;
                    avm_m0_byteenable <= 32'b0;

                    irqFromFPGAMaster <= state[2];
                    if(state[2]==0)     state <= 3'b000;
                    else                    state <= state;
                end
            endcase
        end
        else//Running, but IRQ hasn't been handled yet, preserve some data
        begin
            imgSize <= imgSize;
            irqFromFPGAMaster <= irqFromFPGAMaster;
            //irqFromFPGAMaster <= 0;
            //imgSize <= 32'd0;

            nCntCurPos <= 4'b0;
            nOutWord <= 256'b0;
            state <= 3'b0;
            fifo_read <= 0;
            avm_m0_address <= 27'b0;
            avm_m0_writedata <= 256'b0;
            avm_m0_write <= 0;
            avm_m0_byteenable <= 32'b0;
        end
    end
end

Also just fyi: The bRun Signal is being assigned by an Avalon MM-Slave connected to the ARm-Processor of the Cyclone V. During the observed period there hasn't been any communication with the processor so bRun shouldn't change. This also wouldn't explain the NRZ bus, which should be RZ, as seen in the Verilog code.

\$\endgroup\$
  • \$\begingroup\$ so you have a critical signal controlled by an external MCU, with unknown GROUND-to-GROUND noise between the 2 systems? \$\endgroup\$ – analogsystemsrf Dec 24 '17 at 1:42
  • \$\begingroup\$ It could an IO cable or probe gnd induced EMI problem. If it functions a self test without I/O cables at full speed, then you know crosstalk or cable quality could be an issue. \$\endgroup\$ – Tony Stewart Sunnyskyguy EE75 Dec 24 '17 at 1:58
  • 4
    \$\begingroup\$ Does the timing analyzer tell you that the design SHOULD run at 200 or 325 MHz? \$\endgroup\$ – Dave Tweed Dec 24 '17 at 4:43
6
\$\begingroup\$

Since you say you met the correct functionality at 2 MHz, but not in higher frequency. It is most probably a setup/hold timing violation. Do timing analysis of the entire design for clock constraint 325 MHz and verify that your design will work at 325 MHz. Then proceed to on-board testing.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.