J.Clam
J.Clam

Reputation: 9

two clock ring counter with verilog

I'm trying to write a roll shift/ ring counter that takes two switches as the clocks in verilog.

My code is as follows:

module roll(CLK1, CLK2, LEDS);
input CLK1;
input CLK2;
output [3:0] LEDS;
reg [3:0] LEDS;


initial 
begin
LEDS = 4'b0001;
end


always@(posedge CLK1 or posedge CLK2)
begin
if(CLK1)
begin

         LEDS[3]<=LEDS[2];
         LEDS[2]<=LEDS[1];
      LEDS[1]<=LEDS[0];
         LEDS[0]<=LEDS[3];
end

// Roll Right
if(CLK2)
begin
         LEDS[3]<=LEDS[0];
         LEDS[2]<=LEDS[3];
         LEDS[1]<=LEDS[2];
         LEDS[0]<=LEDS[1];

 end
end
endmodule

I tried using two always blocks, but then figured out that I cannot do that. and when I have the posedge CLK2 in the always statement, the leds on my FPGA all stay on.

Upvotes: 0

Views: 1465

Answers (1)

The Photon
The Photon

Reputation: 1367

Remember Verilog is not a programming language it is a hardware description language.

And when coding for synthesis, you will only be successful if you write code that can be instantiated with actual gates. So writing an always block with sensitivity to edges of two different signals can't be synthesized unless the response to one of the two signals has the effect of a RESET or PRESET operation.

Your code also logically doesn't do what it seems you want to. Consider what your code says will happen if there is a rising edge on CLK2 when CLK1 is already high (or vice versa). Your lights will roll left and then immediately roll right gain, resulting in no change.

A more usual approach would be to have a clock running much faster than the UP and DOWN inputs are expected to change, and use that to drive the logic. For example

module roller(input clk, input rst, input UP, input DOWN, output reg LEDS[3:0]);

reg UP1, DOWN1;

always @(posedge clk or posedge rst)
if (rst) begin
    LEDS[3:0] <= 4'b0001;
end 
else
begin
    UP1 <= UP;
    DOWN1 <= DOWN;
    if (UP & ~UP1) begin
         LEDS[3:0] <= {LEDS[2:0], LEDS[3]};
    end
    else if (DOWN & ~DOWN1) begin
         LEDS[3:0] <= {LEDS[0], LEDS[3:1]};
    end
end
endmodule;

Notice that this gives priority to UP. If both UP and DOWN are asserted, the pattern will roll "up" rather than down. If you want a different behavior, you'd have to modify the code to achieve it.

Upvotes: 6

Related Questions