Xilinx Johnson counter Verilog example bug?

Dec 23, 2003 3 Replies

Greetings:



I have set out to learn Verilog, and thus to learn to use the ModelSim XE II v5.7c Starter simulation program that comes with Xilink WebPack



5.2i. Yesterday I got the software all installed and ready for today's first venture into my shiny new textbook "A Verilog HDL Primer" by J Bhasker.

I began by making sure I knew how to use the software by compiling and simulating the example jc2_top.v together with jc2_test.tf (the test bench) from the WebPack .../ISEexamples/jc2_ver directory.



The readme for the verilog source says that it should implement a Johnson counter with the pattern (depending on the count direction selected):



left right



0000 0000
0001 1000
0011 1100
0111 1110
1111 1111
1110 0111
1100 0011
1000 0001
0000 0000 (repeats)


But in fact the counter produces the following result in the simulator (initial state not shown, only repeated pattern):



left right



0001 1000
0011 1100
0111 1110
1110 0111
1100 0011
1000 0001
0001 1000 (repeats)

The Verilog they provided is (just counter section within an always @ (posedge clk) begin procedural construct):



//Counter section: if(run) begin if(dir) begin q[3:1] = q[2:0]; //Shift lower bits (Left Shift) q[0] = !q[3]; //Circulate inverted MSB to LSB end else begin q[2:0] = q[3:1]; //Shift upper bits (Right Shift) q[3] = !q[0]; //Circulate inverted LSB to MSB end end


Before knowing anything at all about Verilog, I proceded to tinker with this code. I suspected that this represents stated logic, and so all statements are executed in parallel at each clock edge (which turns out not to be the right assumption, which I learned after reading a bit from my Verilog text).



So I modified the code to be this way to test this hypothesis:



//Counter section: if(run) begin if(dir) begin q[0] = !q[3]; //Circulate inverted MSB to LSB q[3:1] = q[2:0]; //Shift lower bits (Left Shift) end else begin q[3] = !q[0]; //Circulate inverted LSB to MSB q[2:0] = q[3:1]; //Shift upper bits (Right Shift) end end



Which of course produced the following pattern:



left right



0011 1100
0111 1110
1111 1111
1100 0011
1000 0001
0000 0000
0011 1100 (repeats)

This led me to suspect that the code is actually executed sequentially not in parallel. Looking at my new Verilog text confirmed this to be the case.



The questions are thus:


  1. Why did Xilinx incorrectly implement what was described in the README?


  1. Has anyone encountered this screwed up example before?

  2. What is the correct implentation?

Oh no, that's too easy. I'm supposed to be learning this language, so I'll take a crack at it.



After several frustrating attempts to fix the counter code, I realized that there was no conceivable logic with which to determine the value of the q[0] bit *after* copying the q[2:0] bits over the q[3:1] bits, because I need to work with the original q[3] bit (left counting case).



One way would be to put in another register bit, but this would be a kuldgy waste of ffs. At the brink of demoralization (and recognizing that the brick wall was self-imposed by my not knowing how to do anything besides the behavioral style of coding, which forces the sequential execution which I don't want, I finally happened upon the answer to my hopes: a way to assign the bits of the result based on the bits of the previous state, all in parallel. That is the concatenation operation, leading to:



//Counter section: if(run) begin if(dir) begin q[3:0] = {q[2], q[1], q[0], ~q[3]}; end else begin q[3:0] = {~q[0], q[3], q[2], q[1]}; end end



Whew, it works!



What a way to learn a language. This was my first day of Verilog. I planned to start by typing in an example from my textbook, but instead I just couldn't resist trying to fix the Xilinx example. Now off to typing in my first Verilog code from scratch to finish.



Good day!


____________________________________ Christopher R. Carlen Principal Laser/Optical Technologist Sandia National Laboratories CA USA crcarle@sandia.gov

Hi -

Verilog has both a blocking assignment (the type that appears in your code fragment, and which uses the = sign) and a non-blocking assignment, in which "=" is replaced by "

Jeez. More blocking assignments in clocked always blocks! Further proof of my assertion that models and examples are built by a company's most junior engineers, and that the companies involved don't bother checking anything before throwing it up on the web. The only possible explanation is that they just don't care.

If we can't trust the examples, how can we trust the post-P&R simulation models?

Good points. I guess I will be cautious about using the examples for coding style.

I will be diving in to the text seriously starting Monday when I'm back to work. Hopefully the text will learn me the right way.

Good day and thanks for the input.

_____________________ Christopher R. Carlen crobc@earthlink.net Suse 8.1 Linux 2.4.19

Join the Discussion

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

Didn't find your answer?

Ask the community — no account required