I want to design a synchronous gray code counter which is 10 bits wide in SystemVerilog. The counter should have an Active HIGH synchronous reset.
I know how to design a 3 bit gray code counter like this:
module gray_code3(input logic reset, clk, output logic [2:0]q);
always_ff @(posedge clk) begin
if (reset)
q <= 0;
else
case (q)
3'b000: q <= 3'b001;
3'b001: q <= 3'b011;
3'b011: q <= 3'b010;
3'b010: q <= 3'b110;
3'b110: q <= 3'b111;
3'b111: q <= 3'b101;
3'b101: q <= 3'b100;
3'b100: q <= 3'b000;
default: q <= 3'bx;
endcase
end
endmodule
Using the same technique would be very tedious for gray code counter of large widths. How to design gray code counters of large widths?
Best Answer
The design is partitioned into 2 parts - one for combinational logic and another for sequential logic.
In the sequential logic part, an always_ff block is used. Counter is an internal signal used to store the values and it gets incremented on the positive edge of the clock. Counter is a binary counter, and it has a modulus of 2 raised to the power of its width.
In the combinational logic part, an always_comb block is used, where the binary code to gray code conversion is done. This is done by observing two facts:
The Most Significant Bit is the same as the Most Significant Bit of the binary counter. This assignment can be done using an assign statement.
For other bits, they are the result of the Ex-Or operation on the corresponding bit of the binary counter and the bit to the immediate right of it. Hence a foreach loop is suitable to iterate over all the bits and perform the Ex-Or operation over the respective bits of the binary counter.
Design:
Testbench: