Skip to content

Sequences

Conner edited this page May 24, 2022 · 8 revisions

WORK IN PROGRESS

Sequences

SequenceExample(
    in Clk,
    out reg [4] A@(Clk) = 0,
    out reg [4] B@(Clk) = 9)
{
    @(Clk)
    {
        A <= 1;
        A <= 2;

        //parallel
        {
            A <= 3;
            B <= 5;
        }

        //parallel
        {
            @(clk)
            {
                A <= 4;
                A <= 5;
            }
            B <= B + 1;
        }

        A <= 0;
        B <= 0;
    }
}

//           __    __    __    __    __    __    __  
//Clk ______/  \__/  \__/  \__/  \__/  \__/  \__/  \_
//A   0     1     2     3     4     5     0          
//B   9                 5     6     7           0    
SequenceExample(
    in Clk,
    out reg A@(Clk) = 0,
    out reg B@(Clk) = 0,
    out reg C@(Clk) = 0,
    out reg [8] D@(Clk) = 0)
{
    reg [4] counter@(Clk) = 0;

    counter <= counter+1;

    @(Clk)
    {
        {A <= 1; B <= 1;}

        @(counter==3);

        {A<=0; C<=1}

        @(counter==6)
        {
            B <= 0;
            C <= 0;
        }

        A <= 1;

        {
            D <= D+1;
            @(counter==11)
            {
                D <= 0;
            }
        }

        A <= 0;
    }
}

//               __    __    __    __    __    __    __    __    __    __    __    __  
//Clk     ______/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \__/  \_
//counter |0    |1    |2    |3    |4    |5    |6    |7    |8    |9    |10   |11   |12  
//A       |0    |1                |0                |1                            |1   
//B       |0    |1                            |0                                       
//C       |0                      |1          |0                                       
//D       |0                                              |1    |2    |3    |0         

Sequences

A sequence can be described using the sequence construct.

Sequencer(
    in Clk,
    out reg A@(Clk),
    out reg B@(Clk),
    out reg C@(Clk),
    out reg D@(Clk),
    out reg E@(Clk),
    out Q)
{

    //Default is 0
    Q = 0;

    sequence@(Clk) //Positive edge of Clk
    {
        //Step 1
        A <= 1;
        B <= 0;
        C <= 0;
        D <= 0;
        E <= 0;

        @(/*No condition*/); //Wait for Clk pulse

        //Step 2
        A <= 0;
        B <= 1;

        @(); //Wait for Clk pulse

        //Step 3
        B <= 0;
        C <= 1;
        D <= 1;
        Q = 1; //Assign to 1 during this state

        @(); //Wait for Clk pulse

        //Step 4
        C <= 0;
        E <= 1;
    }
}

A sequence is defined along with a clock. This clock controls the state machine, and all operations are synchronous to it.

The @ symbol specifies the condition to move onto the next state. If no condition is specified, the sequence moves to the next state on the next clock edge.

If no wait condition after the final step is specified, it will automatically transition back to the first step on the next clock. (Equivalent to a final @();). If a wait condition is explicitly stated (and followed by no other code), the automatic clock will not be inserted, and the explicit condition will be used instead.

The timing diagram produced by the code looks like this:

Step 1     2     3     4     1     
      __    __    __    __    __   
Clk _/  \__/  \__/  \__/  \__/  \__
     |______     |     |     | ____
A   UU      \_________________/    
     |     | _____     |     |     
B   UU______/     \________________
     |     |     | _____     |     
C   UU____________/     \__________
     |     |     | ___________     
D   UU____________/           \____
     |     |     |     | _____     
E   UU__________________/     \____
     |     |     |_____|     |     
Q   _____________/     \___________

Signals are shown initialized to U because they have no initial value so their value is unknown. Q has been given a default value of 0.

In the first step all signals are initialized, with A being set HIGH and all other signals set LOW.

In the second step, A is set LOW and B is set HIGH. The other signals remain unchanged.

On the third step, B is set LOW, and C and D are set HIGH. Q is also assigned HIGH here. Q is not a register so the value of Q is only combinational. That means it is only set HIGH during this state. Since the default is listed before, this assignment takes precedence and overrides it.

On the forth step, C is set back LOW and E is set HIGH. Q is not specified and therefore Q returns to the default value.

At the end of the sequence, it repeats. Therefore all signals are returned to LOW, except for A which is set to HIGH.


Verilog Equivalent

This is the equivalent Verilog code that would produce the same output waveform. The state machine must be created manually.

module Sequencer(
    input Clk,
    output reg A,
    output reg B,
    output reg C,
    output reg D,
    output reg E,
    output Q)
{
    reg [1:0] state;

    // Q = 1 when (state == 3), otherwise Q = 0
    //State is incremented at the same time the outputs are updated. Therefore it is 1 ahead.
    assign Q = (state == 3 ? 1 : 0);

    always @(posedge Clk)
    begin
        state <= state + 1;

        case (state)
        0: //Step 1
            begin
                A <= 1;
                B <= 0;
                C <= 0;
                D <= 0;
                E <= 0;
            end
        1: //Step 2
            begin
                A <= 0;
                B <= 1;
            end
        2: //Step 3
            begin
                B <= 0;
                C <= 1;
                D <= 1;
            end
        3: //Step 4
            begin
                C <= 0;
                E <= 1;
            end
        endcase
    end
end

AXI Bus

wire [4] burstLen;
wire [32] addr;
wire [32] data [8];

wire transfer;

sequence@(Clk)
{
    @(transfer);

    AWaddr <= addr;
    AWvalid <= 1;
    AWlen <= burstLen-1;

    //Fork to handle address and data asynchronously
    fork
    {
        //Write Address
        @(AWready);
        AWaddr <= 32x00000000;
        AWvalid <= 0;
    }
    //Write Data
    {
        @();
        for (int i=0; i<burstLen; i++) //int? reg? var?
        {
            //Post data
            Wdata <= data[i];
            Wvalid <= 1;
            //Assert last on last transfer
            if (i==burstLen-1) { Wlast <= 1; }

            //Wait for acknowledge and loop around for next transfer
            @(Wready);
        }
        //Reset signals
        Wdata <= 32x00000000;
        Wvalid <= 0;
        Wlast <= 0;
    }
    join;

    Bready <= 1;

    //Write Response
    @(Bvalid);
    Bready <= 0;
}

AXI Bus

wire [4] burstLen;
wire [32] addr;
wire [32] data [8];

wire transfer;
reg addrDone;
reg dataDone;
reg sync;


sequence@(Clk)
{
    sync <= 1;

    @(transfer);

    AWaddr <= addr;
    AWvalid <= 1;
    AWlen <= burstLen-1;

    sync <= 0; //Signal to begin address and data

    //Wait for address and data to complete
    @(addrDone && dataDone);
    sync <= 1;

    Bready <= 1;

    //Write Response
    @(Bvalid);
    Bready <= 0;
}

sequence@(Clk)
{
    addrDone <= 0;

    @(!sync && AWready);

    //Write Address
    AWaddr <= 32x00000000;
    AWvalid <= 0;

    //Signal sync
    addrDone <= 1;

    //Wait for sync
    @(sync);
}

sequence@(Clk)
{
    dataDone <= 0;

    @(!sync);

    //Write Data
    for (int i=0; i<burstLen; i++)
    {
        //Post data
        Wdata <= data[i];
        Wvalid <= 1;
        //Assert last on last transfer
        if (i==burstLen-1) { Wlast <= 1; }

        //Wait for acknowledge and loop around for next transfer
        @(Wready);
    }
    //Reset signals
    Wdata <= 32x00000000;
    Wvalid <= 0;
    Wlast <= 0;

    //Signal sync
    dataDone <= 1;

    //Wait for sync
    @(sync);
}

State machine

sequence@(Clk) //Positive edge of Clk
{
State1:
    A <= 1;
    B <= 0;
    C <= 0;
    D <= 0;
    E <= 0;

    @(); //Wait for Clk pulse

State2:
    A <= 0;
    B <= 1;

    @(cond1) goto State1;
    @(cond2) goto State4;

State3:
    B <= 0;
    C <= 1;
    D <= 1;
    Q = 1; //Assign to 1 during this state

    @(cond1) goto State1;
    @(cond2) goto State2;
    @(); //Default transition on next clock

State4:
    C <= 0;
    E <= 1;
}

State machine

sequence@(Clk) //Positive edge of Clk
{
@State1:
    A <= 1;
    B <= 0;
    C <= 0;
    D <= 0;
    E <= 0;

    goto State2; //Wait for Clk pulse

@State2:
    A <= 0;
    B <= 1;

    if (cond1) { goto State1; }
    if (cond2) { goto State4; }

@State3:
    B <= 0;
    C <= 1;
    D <= 1;
    Q = 1; //Assign to 1 during this state

    goto State4; //Default transition on next clock. Must be placed due to overriding rule
    if (cond1) { goto State1; }
    if (cond2) { goto State2; }

@State4
    C <= 0;
    E <= 1;

    goto State1;
}

State machine (Manual)

reg [3] state@(Clk);
wire [3] nextState;

state <= nextState;

Q = 0;

//Next state & Combinational
switch (state)
{
0:
    nextState = 1;

1:
    nextState = 2;

2:
    nextState = 2;
    if (cond1) { nextState = 1; }
    if (cond2) { nextState = 3; }

3:
    Q = 1; //Assign to 1 during this state

    nextState = 4;
    if (cond1) { nextState = 1; }
    if (cond2) { nextState = 2; }

4:
    nextState = 1;
}

switch (nextState)
{
0:
    //Nothing

1:
    A <= 1;
    B <= 0;
    C <= 0;
    D <= 0;
    E <= 0;

2:
    A <= 0;
    B <= 1;

3:
    B <= 0;
    C <= 1;
    D <= 1;

4:
    C <= 0;
    E <= 1;
}

Sequences With Once/Loop/Exit?

WIP


Sequences

sequence@(Clk)
{
    sig1 <= 0;
    sig2 <= 0;

    @(cond1);

    once
    {
        sig1 <= sig1 + 1;
    }
    sig2 <= sig2 + 1;

    @(cond2);
}

Sequences

sequence@(Clk)
{
Init:
    A <= 0;
    B <= 0;
    C <= 0;

    @(cond1);

State1:
    A <= 1;
    B <= 1;
    C <= 1;

    @(cond2) goto Init,
    @(cond3);

State2:
    A <= 1;
    B <= 1;
    C <= 1;

    @(cond4) goto Init,
    @(cond5) goto State1,
    @(false);

State3:
    A <= 1;
    B <= 1;
    C <= 1;

    @(cond6);
}
sequence@(Clk)
{
Init:
    A <= 0;
    B <= 0;
    C <= 0;

    @(cond1);

State1:
    A <= 1;
    B <= 1;
    C <= 1;

    if (cond2)
    {
        goto Init;
    }
    @(cond3); //What happens if omitted?

State2:
    A <= 1;
    B <= 1;
    C <= 1;

    if (cond4) { goto Init; }
    if (cond5) { goto State1; }
    goto State2; //Overriding?

State3:
    A <= 1;
    B <= 1;
    C <= 1;

    @(cond6);
}