Synchronous Binary counter question.

Sep 25, 2003 11 Replies

Hello All



OK Im a bit confused.



the verilog code



always @(posedge CLK or posedge CLR) begin if (CLR) Q


because

Gray counters should count through all possible counts. I do hope you are not changing the address on the SRAM with write enable active.

-- glen

I am confused by your terminology.

Correct me if I am wrong.

  1. You are looking for a "synchrounous binary counter". Isn't it the one you just wrote?
  2. What is the matter with ripple counter? And what is the difference from a "synchrounous binary counter"?
  3. Gray code should be able to walk through all the addresses.

Ok I was confused.

I did implement a synchronous counter as everybody points out. The glitches are due to routing delays in the FPGA.

Now Im not confused any more.

All I need now is to find verilog for a 16 bit gray code counter.

Many thanks

Denis

Try this. Credit where credit is due: as noted in the comments, the gray code calculation comes from a paper by Cliff Cummings.

Bob Perlman Cambrian Design Works

//=============================================================== // Module //=============================================================== // // Module: gray_ctr_module.v // // Author: Bob Perlman // // Description: The Verilog code for a gray-code counter // incorporates a gray-to-binary converter, a binary- // to-gray converter and increments the binary value // between conversions. // // This code was based on Cliff Cummings' 2001 SNUG paper, // "Synthesis and Scripting Techniques for Designing // Multi-Asynchronous Clock Designs." // // Revision history: // Rev. Date Modification // ---- --------

---------------------------------------------- // - 12/29/01 Baseline version

`timescale 1 ns / 1 ps module gray_ctr_module (// Outputs gray_ctr, // Inputs inc_en, preload_en, preload_val, clk, global_async_reset );

//================== // Parameters //==================

parameter SIZE = 4;

//================== // Port declarations //==================

output [SIZE-1:0] gray_ctr;

input inc_en; input preload_en; input [SIZE-1:0] preload_val; input clk; input global_async_reset; // Global asynchronous reset

//==================================================== // Reg, wire, integer, task, and function declarations //====================================================

reg [SIZE-1:0] gray_plus_1, gray_ctr, bnext, bin; integer i;

//================= // Logic //=================

always @(posedge clk or posedge global_async_reset) gray_ctr i); bnext = bin + 1; gray_plus_1 = (bnext>>1) ^ bnext; end

endmodule

If he's using Icarus, older versions (a couple of months back) prior to the RoSync fix for the VCD writer would dump a value change entry per bitchange. As such, you could observe the value updating from the LSB->MSB if you'd look at the VCD file in a text editor.

formatting link
formatting link

-t

I once wrote a program to explore gray code sequences (more than ten years ago). You can download it from:

formatting link

It will generate Verilog for part of a case statement. For three bits you could do:

./jct 3 ./jct is starting up case 10'b000: ns = 10'b001; case 10'b001: ns = 10'b011; case 10'b011: ns = 10'b010; case 10'b010: ns = 10'b110; case 10'b110: ns = 10'b111; case 10'b111: ns = 10'b101; case 10'b101: ns = 10'b100; case 10'b100: ns = 10'b000; ./jct is finishing up

There's also another program called jc which will generate all possible sequences, but you have to build the set of numbers in the source. Here's the output for three bits

Set permute

0 1 3 2 6 4 5 7 0 1 3 2 6 7 5 4 circular 0 1 3 7 5 4 6 2 circular 0 1 5 4 6 2 3 7 0 1 5 4 6 7 3 2 circular 0 1 5 7 3 2 6 4 circular 0 2 3 1 5 4 6 7 0 2 3 1 5 7 6 4 circular ... 7 6 4 0 2 3 1 5 circular 7 6 4 5 1 0 2 3 circular 7 6 4 5 1 3 2 0

The program will give some errors/warning if compiled on a recent g++, but this should be easy to fix by moving the "unsigned int i" out of the for loop. C++ wasn't even a standard when I started programming in C++ in the late 80's. The reference was the "cfront" implementation by AT&T.

Petter

A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing on usenet and in e-mail?

You needn't be concerned with the glitches if the counter outputs will be used synchronously, assuming, of course, that the counter outputs are stable by the next clock edge. Your static timing analyzer will tell you if you win or not.

I think I have a significantly simpler implementation of a Gray counter:

Start with a plain-vanilla binary counter. Add to it a register of equal length, where the Gray count value will appear. Drive each Di input of the Gray register with the XOR of the binary counter's Di and Di+1 inputs, since any Gray bit is the XOR of the two (equivalent and equivalent+1) binary bits. The subtle trick is to not use the binary Q outputs, but rather their D inputs to drive the Gray register, which avoids having the Gray counter trail the binary counter. (Good when the counter has a CE input).

Peter Alfke, Xilinx Applications =========================

Bob Perlman wrote:

If you want the best speed and have the extra (~2X) FFs to spare, Peter's is the better solution, at least for longer counters. Here's the Verilog code for the implementation. I've synthesized but not simulated it, so I can't promise that it works.

Hoping that this wasn't a homework problem, Bob Perlman Cambrian Design Works

//=============================================================== // Module //=============================================================== // // Module: gray_ctr_module.v //

`timescale 1 ns / 1 ps module gray_ctr_module (// Outputs gray_ctr, // Inputs inc_en, clk, global_async_reset );

//================== // Parameters //==================

parameter SIZE = 16;

//================== // Port declarations //==================

output [SIZE-1:0] gray_ctr;

input inc_en; input clk; input global_async_reset; // Global asynchronous reset

//==================================================== // Reg, wire, integer, task, and function declarations //====================================================

reg [SIZE-1:0] gray_ctr, binary_ctr;

wire [SIZE-1:0] next_binary_ctr_val, next_gray_ctr_val;

//================= // Logic //=================

assign next_binary_ctr_val = binary_ctr + 1;

always @(posedge clk or posedge global_async_reset) binary_ctr >1) ^ next_binary_ctr_val;

always @(posedge clk or posedge global_async_reset) gray_ctr

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required