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:
- Why did Xilinx incorrectly implement what was described in the README?
- Has anyone encountered this screwed up example before?
- 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!