• 0

PmodCLP - Sample project timing errors


Question

I just got a PmodCLP and downloaded the verilog files here:

https://reference.digilentinc.com/reference/pmod/pmodclp/start

Specifically, the 

 
code. 

Since I'm using an Artix Arty board, I had to modify the pins used, and the reset is reversed (on the arty the ck_rst is 1 when pressed), but after that things worked fine. The Arty, like the Nexys 3 has a 100MHz clock.
 
In looking at the code, however, I noticed two errors that make the code quite confusing:

1) In the first always block:
 
    // This process counts to 100, and then resets.  It is used to divide the clock signal.
    // This makes oneUSClock peak aprox. once every 1microsecond
    always @(posedge CLK) begin

            if(clkCount == 7'b1100100) begin
                    clkCount <= 7'b0000000;
                    oneUSClk <= ~oneUSClk;
            end
            else begin
                    clkCount <= clkCount + 1'b1;
            end

    end

Note that it is flipping the oneUsClk once per 100 clocks at the 100MHz input rate. That results in a full cycle every 200 clocks, not 100. To get a 1MHz clock that has a rising edge every 1μs, you need to flip the clock every 0.5μs or 50 clock edges of the 100Mhz clock. But replacing the 100 with 50 won't be correct either, you can't get 100 clock edges by counting from 0 to 100, that's 101 edges. And you can't get 50 edges by counting from 0 to 50,  the correct code need to count from 0 to 49 to get 50 edges.

The second issue is that the delays are all based on this oneUsClk, while the delay counts are expressed in terms of the original 100MHz clock ticks. You can see that in this combinatorial logic:
 

    // Determines when count has gotten to the right number, depending on the state.
    assign delayOK = (
                ((stCur == stPowerOn_Delay) && (count == 21'b111101000010010000000)) ||                // 2000000         -> 20 ms
                ((stCur == stFunctionSet_Delay) && (count == 21'b000000000111110100000)) ||        // 4000             -> 40 us
                ((stCur == stDisplayCtrlSet_Delay) && (count == 21'b000000000111110100000)) ||    // 4000             -> 40 us
                ((stCur == stDisplayClear_Delay) && (count == 21'b000100111000100000000)) ||        // 160000         -> 1.6 ms
                ((stCur == stCharDelay) && (count == 21'b000111111011110100000))                        // 260000        -> 2.6 ms - Max Delay for character writes and shifts
    ) ? 1'b1 : 1'b0;


The delay for the stPowerOn_Delay is 2,000,000. That's correct for a 100MHz clock.  For a 1MHz clock with a rising edge every 1μs, you only want a count of 20,000 not 2,000,000. All of the times are off by this same factor of 100. You can see in the block that increments the count variable that this is being incremented each posedge of the oneUSClk, not the 100MHz CLK:

    // This process increments the count variable unless delayOK = 1.
    always @(posedge oneUSClk) begin
    
            if(delayOK == 1'b1) begin
                    count <= 21'b000000000000000000000;
            end
            else begin
                    count <= count + 1'b1;
            end
    
    end

So the 20ms delay is actually a 2 second delay, 1.6ms is 160ms, etc.

Finally, if you fix this, you will notice that things don't quite work anymore. The LCD display is now flashing and barely legible because it is now executing the final command (shift-left) every 2.6ms, which is far too fast. So, you'll need to alter the delay for the final state stCharDelay when the write is done to be a more appropriate number. I suggest 250,000μs which means 4 characters scroll by per second which is very legible. This is most easily done by adding an additional condition check for the final state delay like:

    // Determines when count has gotten to the right number, depending on the state.
    assign delayOK = (
        ((stCur == stPowerOn_Delay) &&              (count == 21'd020000)) ||	// -> 20 ms
        ((stCur == stFunctionSet_Delay) &&          (count == 21'd000040)) ||	// -> 40 us
        ((stCur == stDisplayCtrlSet_Delay) &&       (count == 21'd000040)) ||	// -> 40 us
        ((stCur == stDisplayClear_Delay) &&         (count == 21'd001600)) ||	// -> 1.6 ms
        ((stCur == stCharDelay && !writeDone) &&    (count == 21'd002600)) ||	// -> 2.6 ms - Max Delay for character writes and shifts
        ((stCur == stCharDelay && writeDone) &&     (count == 21'd250000))      // -> 250 ms - 1/4 second delay for shifts
    ) ? 1'b1 : 1'b0;

where the delay before all the characters are written is 2.6ms and it jumps to 250ms once they are all written.

I have attached a file which reflects the corrections I outlined above.


 

PmodCLP.v

Edited by inflector
typo
Link to post
Share on other sites

1 answer to this question

Recommended Posts

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now