TheSprintingEngineer
TheSprintingEngineer

Reputation: 319

system verilog always within always

I am wondering if this syntax is allowed

always_comb begin
    case (aaa)
    3'b000: always #(CLKREF_HALF_PERIOD + 5000ps) xclk=~xclk ;//000 at 80MHZ :
    3'b001: always #(3750ps + CLKREF_HALF_PERIOD) xclk=~xclk;//001 at 100MHZ
    3'b010: always #(1250ps + CLKREF_HALF_PERIOD) xclk=~xclk;//010 at 200MHZ
    3'b011: always #(0.252ns + CLKREF_HALF_PERIOD) xclk=~xclk;//011 at 333MHZ
    3'b100: always #(0.112ns + CLKREF_HALF_PERIOD) xclk=~xclk;//100 at 367MHZ

    default always #(CLKREF_HALF_PERIOD/1) xclk=~xclk;//default at 400MHZ   
            endcase 

I am getting compilation errors regarding the nested always within the cases. i am trying to get the clock freq to change depending on the input of aaa. however the question is more of a question on "if an always within an always block is legal or not"

Upvotes: 0

Views: 6369

Answers (2)

sharvil111
sharvil111

Reputation: 4381

Nested procedural blocks are not allowed. I believe that aaaaaa is a parameter over here. If so, you can use generate block. to use different clock frequencies. This will make a single combinational block active at a time. A sample code can be as follows:

generate 
    case (aaaaaa)
    3'b000: always #(CLKREF_HALF_PERIOD + 5000ps) xclk=~xclk ;//000 at 80MHZ :
    3'b001: always #(3750ps + CLKREF_HALF_PERIOD) xclk=~xclk;//001 at 100MHZ
    3'b010: always #(1250ps + CLKREF_HALF_PERIOD) xclk=~xclk;//010 at 200MHZ
    3'b011: always #(0.252ns + CLKREF_HALF_PERIOD) xclk=~xclk;//011 at 333MHZ
    3'b100: always #(0.112ns + CLKREF_HALF_PERIOD) xclk=~xclk;//100 at 367MHZ

    default always #(CLKREF_HALF_PERIOD/1) xclk=~xclk;//default at 400MHZ 

endgenerate

If aaa is a variable/register/wire then you can use forever looping construct instead of inner always block. Sample usage is shown more clearly in Dave_59's answer.

Refer IEEE 1800-2012 Section 27.5 for more information on generate blocks.

Upvotes: 1

dave_59
dave_59

Reputation: 42738

The forever loop solution does not work because there is no way for the top level always block to exit for the forever loop and get to another branch of the case statement. A simpler solution is to use an always block to compute the clock delay, and another always block to create the clock.

int clk_delay;
always_comb
    case (aaa)
    3'b000: clk_delay = CLKREF_HALF_PERIOD + 5000ps; //000 at 80MHZ
    3'b001: clk_delay = 3750ps + CLKREF_HALF_PERIOD; //001 at 100MHZ
...
always #clk_delay xclk = ! xclk;

Upvotes: 2

Related Questions