verilogvivadosynthesis

Variable output stream delay attempt not working


The module I'm trying to get working takes in a pulse data stream with pulses occurring between 500 and 12500 clk cycles, and it needs to delay the stream by a specified number of clk cycles between 500 and 12500 clk cycles. But without using a 12500 bit shift register.

I wrote some code that works in the behavioral simulation, but doesn't post-synthesis. I know my solution is probably terrible form from a Verilog coders perspective. This is my jumping off point I'm just trying to get something working just using what my brain comes up with. My specific problem I think shows up in the schematic view pretty clearly, before synthesis the schematic looks like this:

Before Synthesis Schematic

Which already doesn't make sense to me cause zooming in on the output s_OUT, I see this:

Before Synthesis Schematic Zoomed In

The output seems to just be ground connected to a buffer, but in behavioral simulation it works. After synthesis however the schematic gets rid of all the other stuff not connected to the output and just leaves that buffer and output pin and it no longer works in simulation:

Post Synthesis Schematic

I'd like to know if there's a rule I'm breaking in my Verilog code that's causing this or if its something else:

module data_delay_counter(
    input clk,
    input en,
    input [13:0] ShiftNum,
    input s_IN,
    output reg s_OUT
    );
    
    // counting phase
    reg [13:0] cyclesToInputPulse = 0; // counted clk cycles before a pulse
    // storage phase
    reg [4:0] memoryIndxWrite = 0; // index to write pulse information to
    reg [13:0] storage [0:24]; // memory for pulse information
    // delay phase
    reg [13:0] delayCounter = 0; // output delay counter
    // output phase
    reg [4:0] memoryIndxRead = 0; // index to read out pulse information from
    reg [13:0] cyclesToOutputPulse = 0; // counted clk cycles up to number read out from storage
    reg [24:0] unusedStorage = 0; // specifies if storage pulse info has been used or not, 1 for unused 0 for used
      
    always @(posedge clk) begin
        if (en == 1) begin
            // counting phase
            if (s_IN != 1)
                cyclesToInputPulse = cyclesToInputPulse + 14'd1;
            else begin
            // storage phase  
                cyclesToInputPulse = cyclesToInputPulse + 14'd1;
                storage[memoryIndxWrite] = cyclesToInputPulse;

                unusedStorage[memoryIndxWrite] = 1;
                cyclesToInputPulse = 14'd0;
                memoryIndxWrite = memoryIndxWrite + 14'd1;
                if (memoryIndxWrite == 25)
                    memoryIndxWrite = 14'd0;
                
            end
            // delay phase
            if (delayCounter != ShiftNum)
                delayCounter = delayCounter + 1;
            // output phase
            else begin
                cyclesToOutputPulse = cyclesToOutputPulse + 14'd1;
                if (cyclesToOutputPulse == storage[memoryIndxRead] && unusedStorage[memoryIndxRead] == 1) begin
                    s_OUT = 1;
                    unusedStorage[memoryIndxRead] = 0;
                    cyclesToOutputPulse = 14'd0;
                    memoryIndxRead = memoryIndxRead + 14'd1;
                    if (memoryIndxRead == 25)
                        memoryIndxRead = 0;
                end
                else begin
                    s_OUT = 0;
                end
            end
        end
        else begin
            cyclesToInputPulse = 0;
            memoryIndxWrite = 0;
            delayCounter = 0;
            cyclesToOutputPulse = 0;
            memoryIndxRead = 0;
            unusedStorage = 0;
            s_OUT = 0;
        end
    end 
   
    always @(ShiftNum) begin
        cyclesToInputPulse = 0;
        memoryIndxWrite = 0;
        delayCounter = 0;
        cyclesToOutputPulse = 0;
        memoryIndxRead = 0;
        unusedStorage = 0;
        s_OUT = 0;
    end

The process I was thinking to use was have 25, 14 bit registers as memory to handle the worst case of a pulse every 500 cycles and max delay of 12500 cycles, count the cycles to each pulse store them in memory, wait for the delay and output the pulses according to what's stored in memory. And I needed to add that unusedStorage parameter in order to ensure it always used each stored memory delay only once.


Solution

  • The first problem I see is that you are making assignments to signals from multiple always blocks. For example, s_OUT is assigned in both of your always blocks. While this is legal for simulations, it is likely causing problems for synthesis.

    Another issue with the 2nd block is that the signal in the sensitivity list (ShiftNum) is not used within the block; typically, all signals in the list would also be "read" (i.e., appear on the RHS of an assignment). This block does not map to a conventional synthesis construct.

    I recommend incorporating all the assignments from the 2nd always block into the 1st somehow.

    If you have log files for your synthesis run, take a look in them. I'd be surprised if you didn't get warning messages for any of this.


    It is also good practice to use nonblocking assignments (<=) in clocked always blocks.