Reply by Chris Carlen January 4, 20042004-01-04
Andy Peters wrote:
> Chris Carlen <crcarle@BOGUS.sandia.gov> wrote in message news:<bsa1a102rfm@enews3.newsguy.com>... > >>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 > > > 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? > > --a
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
Reply by Andy Peters December 26, 20032003-12-26
Chris Carlen <crcarle@BOGUS.sandia.gov> wrote in message news:<bsa1a102rfm@enews3.newsguy.com>...
> 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
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? --a
Reply by Bob Perlman December 23, 20032003-12-23
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 "<=".  With non-blocking
assignments, the right side of the assignment is saved in a temp
variable that you never see.  The temp variable is then transferred to
the left-hand side only after all such temp assignments have been made
for the clock event in question, including events that occur in other
always statements.  It's sort of the way things are actually done in
hardware, with data being stored in a master latch that closes at the
start of the new clock cycle, then transferred to a slave latch.
(Note to Verilog gurus: I know how inadequate an explanation this is,
but what were you expecting from a hardware designer?)

Try replacing:
          q[3:1] = q[2:0];     //Shift lower bits (Left Shift)
          q[0] = !q[3];	      //Circulate inverted MSB to LSB
with
          q[3:1] <= q[2:0];   //Shift lower bits (Left Shift)
          q[0] <= !q[3];      //Circulate inverted MSB to LSB

Bob Perlman
Cambrian Design Works

On Tue, 23 Dec 2003 10:25:05 -0800, Chris Carlen
<crcarle@BOGUS.sandia.gov> wrote:

>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? > >2. Has anyone encountered this screwed up example before? > >3. 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!
Reply by Chris Carlen December 23, 20032003-12-23
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?

2.  Has anyone encountered this screwed up example before?

3.  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