Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

3 bit Gray counter

ppinus

Newbie level 4
Newbie level 4
Joined
Jun 26, 2024
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
76
I need help to create a 3-bit Gray code counter that can count both forwards and backwards. Using flip-flops as memory, I was able to create a counter but only in one direction. The dir signal, despite changing, cannot reverse the counting direction. The flip-flop needs to have the same value as input to change the exit. I noticed that the counter counts only in the direction it is in at the time of the reset. When dir = 0 it should count from 0 to 7 and when dir = 1 from 7 to 0. I do not waant to change the flipflop.
This is the simulation:
gray-counter-simulation.png


This is the verilog code:


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
module gray_counter(
    input clk,
    input reset,
    input dir,
    output [2:0] out
);
 
wire [2:0] stato_attuale;
reg [2:0] eccitazione;
 
 
always @(posedge clk) begin
 
    if (dir == 0) begin
        eccitazione[0] <= ((~stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                      (~stato_attuale[2] & stato_attuale[1] & stato_attuale[0]) |
                      (stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                      (stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]));
 
    eccitazione[1] <= ((~stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]) |
                      (stato_attuale[2] & stato_attuale[1] & stato_attuale[0]));
 
    eccitazione[2] <= ((~stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                      (stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]));
    end
 
    else if (dir == 1) begin
        eccitazione[0] <= ((stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                      (stato_attuale[2] & stato_attuale[1] & stato_attuale[0]) |
                      (~stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                      (~stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]));
 
    eccitazione[1] <= ((stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]) |
                      (~stato_attuale[2] & stato_attuale[1] & stato_attuale[0]));
 
    eccitazione[2] <= ((~stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                      (stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]));
    end
 
end
 
FF ff0 (.X(eccitazione[0]), .C(eccitazione[0]), .R(reset), .Z(stato_attuale[0]));
FF ff1 (.X(eccitazione[1]), .C(eccitazione[1]), .R(reset), .Z(stato_attuale[1]));
FF ff2 (.X(eccitazione[2]), .C(eccitazione[2]), .R(reset), .Z(stato_attuale[2]));
 
assign out[0] = stato_attuale[0];
assign out[1] = stato_attuale[1];
assign out[2] = stato_attuale[2];
 
endmodule
 
module FF(
    input X, C, R,
    output Z
);
    reg y1, y2;
 
    always @(posedge C or posedge R) begin
        if (R) begin
            y1 <= 1'b0;
            y2 <= 1'b0;
        end else begin
            y1 <= (~y2 & C & X) | (y1 & (~C | ~y2));
            y2 <= y1 ^ C;
        end
    end
 
    assign Z = y1;
 
endmodule

 
Last edited by a moderator:
You can modify your code like this:
Code:
module gray_counter(
    input clk,
    input reset,
    input dir,
    output [2:0] out
);
 
reg [2:0] stato_attuale;
reg [2:0] eccitazione;
 
always @(posedge clk or posedge reset) begin
    if (reset) begin
        stato_attuale <= 3'b000;
    end else begin
        stato_attuale <= eccitazione;
    end
end
 
always @(*) begin
    if (dir == 0) begin
        eccitazione[0] = ((~stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                          (~stato_attuale[2] & stato_attuale[1] & stato_attuale[0]) |
                          (stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                          (stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]));
 
        eccitazione[1] = ((~stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]) |
                          (stato_attuale[2] & stato_attuale[1] & stato_attuale[0]));
 
        eccitazione[2] = ((~stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                          (stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]));
    end else if (dir == 1) begin
        eccitazione[0] = ((stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                          (stato_attuale[2] & stato_attuale[1] & stato_attuale[0]) |
                          (~stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                          (~stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]));
 
        eccitazione[1] = ((stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]) |
                          (~stato_attuale[2] & stato_attuale[1] & stato_attuale[0]));
 
        eccitazione[2] = ((~stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                          (stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]));
    end
end
 
assign out = stato_attuale;
 
endmodule

Here
The eccitazione register is computed combinationally based on the current state stato_attuale and the dir signal.
The stato_attuale register is updated on each clock cycle if reset is not active.
The reset signal ensures that the counter starts from a known state (0 in this case).
 
You can modify your code like this:
Code:
module gray_counter(
    input clk,
    input reset,
    input dir,
    output [2:0] out
);
 
reg [2:0] stato_attuale;
reg [2:0] eccitazione;
 
always @(posedge clk or posedge reset) begin
    if (reset) begin
        stato_attuale <= 3'b000;
    end else begin
        stato_attuale <= eccitazione;
    end
end
 
always @(*) begin
    if (dir == 0) begin
        eccitazione[0] = ((~stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                          (~stato_attuale[2] & stato_attuale[1] & stato_attuale[0]) |
                          (stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                          (stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]));
 
        eccitazione[1] = ((~stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]) |
                          (stato_attuale[2] & stato_attuale[1] & stato_attuale[0]));
 
        eccitazione[2] = ((~stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                          (stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]));
    end else if (dir == 1) begin
        eccitazione[0] = ((stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                          (stato_attuale[2] & stato_attuale[1] & stato_attuale[0]) |
                          (~stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                          (~stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]));
 
        eccitazione[1] = ((stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]) |
                          (~stato_attuale[2] & stato_attuale[1] & stato_attuale[0]));
 
        eccitazione[2] = ((~stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                          (stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]));
    end
end
 
assign out = stato_attuale;
 
endmodule

Here
The eccitazione register is computed combinationally based on the current state stato_attuale and the dir signal.
The stato_attuale register is updated on each clock cycle if reset is not active.
The reset signal ensures that the counter starts from a known state (0 in this case).
Thanks for the idea, but I wanted to keep the flip-flops, as it was an exercise to create a counter using the given flip-flop as the memory cell. The logic is correct, it's just a problem of Verilog syntax. The counter simply stops working when the dir signal changes and I need help fixing it.
 
I've seen counting go downward when taking output from Q pin of D flip-flops. To count upward I find I must take output from bar-Q pins.
What do you mean?
My flipflop exit are stato_attuale[], and my inputs for the flipflops based on the output are eccitazione[]
 
.
Well, then, I guess you've just invented Schroedinger's logic, it works and doesn't work at the same time!
I'm assuming my logic is correct, I think this is just a verilog syntax problem
 
What does this mean? You expect a Verilog compiler
Then I guess my logic is wrong... but I don't know where. My counter stops when dir changes value and I don't know why
 
Your so-called "flip-flop" code is garbage. It neither models an edge triggered nor level triggered flip-flop correctly.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
always @(posedge C or posedge R) begin
        if (R) begin
            y1 <= 1'b0;
            y2 <= 1'b0;
        end else begin
            y1 <= (~y2 & C & X) | (y1 & (~C | ~y2));
            y2 <= y1 ^ C;
        end
    end


The @(posedge C) construct is right for edge triggered logic. But then C must not appear in the edge sensitive logic expression.
Simpled edge triggered FF

Code Verilog - [expand]
1
2
3
4
5
6
always @(posedge C or posedge R) begin
        if (R)
            Z <= 1'b0;
        else
            Z <= X;
    end

 
Your so-called "flip-flop" code is garbage. It neither models an edge triggered nor level triggered flip-flop correctly.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
always @(posedge C or posedge R) begin
        if (R) begin
            y1 <= 1'b0;
            y2 <= 1'b0;
        end else begin
            y1 <= (~y2 & C & X) | (y1 & (~C | ~y2));
            y2 <= y1 ^ C;
        end
    end


The @(posedge C) construct is right for edge triggered logic. But then C must not appear in the edge sensitive logic expression.
Simpled edge triggered FF

Code Verilog - [expand]
1
2
3
4
5
6
always @(posedge C or posedge R) begin
        if (R)
            Z <= 1'b0;
        else
            Z <= X;
    end

Thank you man, I wanted to remain the closest possible to this flipflop (it was an exercise):

module FF(X,C,R,Z);

input X,C,R;
output Z;
wire y1,y2;
assign y1=(~y2&C&X) | (y1&(~C|~y2));
assign y2=y1^C;
assign Z = y1;

endmodule


Can I still work with this flipflop?
 
I need help to create a 3-bit Gray code counter that can count both forwards and backwards. Using flip-flops as memory, I was able to create a counter but only in one direction. The dir signal, despite changing, cannot reverse the counting direction. The flip-flop needs to have the same value as input to change the exit. I noticed that the counter counts only in the direction it is in at the time of the reset. When dir = 0 it should count from 0 to 7 and when dir = 1 from 7 to 0. I do not waant to change the flipflop.
This is the simulation:
gray-counter-simulation.png


This is the verilog code:


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
module gray_counter(
    input clk,
    input reset,
    input dir,
    output [2:0] out
);
 
wire [2:0] stato_attuale;
reg [2:0] eccitazione;
 
 
always @(posedge clk) begin
 
    if (dir == 0) begin
        eccitazione[0] <= ((~stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                      (~stato_attuale[2] & stato_attuale[1] & stato_attuale[0]) |
                      (stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                      (stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]));
 
    eccitazione[1] <= ((~stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]) |
                      (stato_attuale[2] & stato_attuale[1] & stato_attuale[0]));
 
    eccitazione[2] <= ((~stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                      (stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]));
    end
 
    else if (dir == 1) begin
        eccitazione[0] <= ((stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                      (stato_attuale[2] & stato_attuale[1] & stato_attuale[0]) |
                      (~stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]) |
                      (~stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]));
 
    eccitazione[1] <= ((stato_attuale[2] & ~stato_attuale[1] & stato_attuale[0]) |
                      (~stato_attuale[2] & stato_attuale[1] & stato_attuale[0]));
 
    eccitazione[2] <= ((~stato_attuale[2] & ~stato_attuale[1] & ~stato_attuale[0]) |
                      (stato_attuale[2] & stato_attuale[1] & ~stato_attuale[0]));
    end
 
end
 
FF ff0 (.X(eccitazione[0]), .C(eccitazione[0]), .R(reset), .Z(stato_attuale[0]));
FF ff1 (.X(eccitazione[1]), .C(eccitazione[1]), .R(reset), .Z(stato_attuale[1]));
FF ff2 (.X(eccitazione[2]), .C(eccitazione[2]), .R(reset), .Z(stato_attuale[2]));
 
assign out[0] = stato_attuale[0];
assign out[1] = stato_attuale[1];
assign out[2] = stato_attuale[2];
 
endmodule
 
module FF(
    input X, C, R,
    output Z
);
    reg y1, y2;
 
    always @(posedge C or posedge R) begin
        if (R) begin
            y1 <= 1'b0;
            y2 <= 1'b0;
        end else begin
            y1 <= (~y2 & C & X) | (y1 & (~C | ~y2));
            y2 <= y1 ^ C;
        end
    end
 
    assign Z = y1;
 
endmodule

I think I've found the error, basically the counter should change value everytime the clk change, but I have posedge C and non posedge clk. The time that at least one of the input of ff does not change from 0 to 1 the counter stops, as there is not a posedge C that rule the flipflop.
 
Hi,
basically the counter should change value everytime the clk change, but I have posedge C and non posedge clk.
Usually (binary) counters change state on one clock edge only. Not on both edges.

Klaus
 
What do you mean?
My flipflop exit are stato_attuale[], and my inputs for the flipflops based on the output are eccitazione[]
Posedge triggered versus negedge triggered is what I was getting at. By experimenting with my simulations of counters, the scope traces indicate that changes of state depend on whether polarities are one way or the opposite way. In other words, whether positive edge triggered or negative edge triggered. It has to do with Q versus not-Q outputs.

I saw there were 4 different combinations regarding whether Q or not-Q (bar-Q) feeds the following flip-flop. Also whether to take readouts from Q or not-Q. It also makes a difference how you use D FF's or JK FF's. I think that makes 8 different combinations to test.
 

LaTeX Commands Quick-Menu:

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top