C
Chris Carlen
Guest
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
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