Pablo Estrada
Pablo Estrada

Reputation: 3462

Creating a 4 step clock

Im trying to implement 4 clock signals that are activated one after the other in Verilog. I've written a module but Im not sure how to make a testbench for it because Im getting the error:

error: clk_pc Unable to assign to unresolved wires.

I expect a result like this one:

1000
0100
0010
0001
1000
0100
...

This is the module:

module clock_divisor(input clk0,
                    input clk1,
                    input clk2,
                    input clk3, 
                    output clk0_out,
                    output clk1_out,
                    output clk2_out,
                    output clk3_out);

    reg clk0_out,clk1_out,clk2_out,clk3_out;
    always @(posedge clk0 or posedge clk1 or posedge clk2 or posedge clk3) begin
        if(clk0 == 1)begin
            assign clk0_out = 0;
            assign clk1_out = 1;
            assign clk2_out = 0;
            assign clk3_out = 0;
        end
        else if(clk1 == 1)begin
            assign clk0_out = 0;
            assign clk1_out = 0;
            assign clk2_out = 1;
            assign clk3_out = 0;
        end
        else if(clk2 == 1)begin
            assign clk0_out = 0;
            assign clk1_out = 0;
            assign clk2_out = 0;
            assign clk3_out = 1;
        end
        else if(clk3 == 1)begin
            assign clk0_out = 1;
            assign clk1_out = 0;
            assign clk2_out = 0;
            assign clk3_out = 0;
        end
    end

endmodule

And my testbench:

module testbench();
    reg clk_pc, clk_instruction_memory, clk_alu, clk_registers, reset;
    // Clock Management
    clock_divisor clock_divisor (clk_pc,
                                 clk_instruction_memory, 
                                 clk_alu, 
                                 clk_registers,
                                 clk_pc,
                                 clk_instruction_memory, 
                                 clk_alu, 
                                 clk_registers);
    initial begin
      clk_pc = 1;
    end

    initial
     #500 $finish;


  initial begin
    //$display ("   Pc\tCLK\treset\tCurrent-inst");
    //$monitor("   %d\t%b\t%b\t%h", pc, clk_pc, reset, current_instruction);

    //Monitor Clocks
    $display ("   CLK0\tCLK1\tCLK2\tCLK3");
    $monitor("   %b\t%b\t%b\t%b", clk_pc, clk_instruction_memory, clk_alu, clk_registers);
  end

endmodule 

Can anyone tell me why Im getting this error and how can I get my module to work as expected?

Upvotes: 0

Views: 178

Answers (1)

spaceman
spaceman

Reputation: 88

(sorry, my reputation is too low to comment)

Like others said, do not use procedural assignments in always blocks. Sequential elements must only have non-blocking assignments (<=) and combinatorial elements only blocking assignments (=). Don’t mix them within a code block. Also, your design will not synthesize due to multiple signals in always block sensitivity list.

If you want to synchronize your clock signals, just use one of them and sync others to it. This is plain simple if you use a 4-bit rotating shift register and assign clock outputs to a corresponding bit in the shift register.

Shift Register:

module clock_divisor(input clk0,
                input rst_i,
                output clk0_out,
                output clk1_out,
                output clk2_out,
                output clk3_out);

reg [3:0] shift_reg;

always @ (posedge clk0 or negedge rst_i) begin
    if(rst_i) begin
        shift_reg <= 4'd1;
    end
    else begin
        shift_reg <= {shift_reg[2:0], shift_reg[3]};
    end
end

assign clk0_out = shift_reg[0];
assign clk1_out = shift_reg[1];
assign clk2_out = shift_reg[2];
assign clk3_out = shift_reg[3];

endmodule

enter image description here

Frequency of all clock outputs is the same as clk0! They just have a 180° phase shift.

But if you really want to make a clock divider, just use a simple counter:

module clock_divisor(input clk0,
                input rst_i,
                output clk0_out,
                output clk1_out,
                output clk2_out,
                output clk3_out);

reg [3:0] counter;

always @ (posedge clk0 or negedge rst_i) begin
    if(rst_i) begin
        counter <= 4'd0;
    end
    else begin
        counter <= counter + 1'd1;
    end
end

assign clk0_out = counter[0];
assign clk1_out = counter[1];
assign clk2_out = counter[2];
assign clk3_out = counter[3];

endmodule

enter image description here

Now, frequency of clk_out's are:

  • clk0_out = 2*clk0
  • clk1_out = 4*clk0
  • clk2_out = 8*clk0
  • clk3_out = 16*clk0

Hope this helps you!

P.S. Do not forget to add reset signal for registers! This is crucial, so your design can start from a known state.

Upvotes: 1

Related Questions