EmbDev.net

Forum: FPGA, VHDL & Verilog Verilog state machine query


von Kenny M. (kennym)


Attached files:

Rate this post
useful
not useful
I am trying to write a verilog module to read data from an AM2303 (also 
DHT22) temperature and humidity sensor.

The Am2303.v verilog code is attached, along with some images from my 
oscilloscope.

In the verilog module I use a 7-bit register called "state" to implement 
a state machine.

The oscilloscope image shows the inout signal "dhtio" as it comes from 
the sensor, you can see it is very clean. No bounce. It also shows the 
lest-significant-bit of "state" so that you can see exactly when "state" 
changes.

I don't understand why state changes six times on the first rising edge 
of the signal from the sensor.

I expected my state machine to stall at state 8'h02 until the signal was 
high, and then stall at state 8'h03 until the next falling edge.

But as you can see it progresses from state 2 to 7 very rapidly.
Can anyone help me understand this?

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Kenny Millar wrote:
> But as you can see it progresses from state 2 to 7 very rapidly.
Is the simulation of this design working flawlessly?

> Can anyone help me understand this?
You must synchronize external input signals (e.g. dhtin) before using 
them inside. Otherwise this will happen:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html 
(try Google translator, its German).

The input signal dhtin is connected to several FSM stages. Each of them 
is represented by a flipflop inside the FPGA. And the propagation time 
from the input pin to the corresponding state logic differs. Therefore 
some flipflops see the "old" dhtin value, others see the "new" dhtin. 
this will result in strange behaviour...

: Edited by Moderator
von Kenny M. (kennym)


Rate this post
useful
not useful
Thank you, that makes sense.

I haven't completed a simulation, because I'm just a newbie and still 
learning how to simulate the sensor I/O in Lattice Diamond.

So if I change:
    assign dhtin = dhtio;

to:
    always @posedge(clk) begin
        dhtin = dhtio;
    end


I think that will synchronize the input signal?

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Kenny Millar wrote:
> I think that will synchronize the input signal?
It looks like then you will have one FF sync stage. But I'm merely the 
VHDL man... ;-)

BTW:
When you always get the very same picture, there also may be an 
additional structural flaw in the description.

von Kenny M. (kennym)


Rate this post
useful
not useful
Lothar Miller wrote:
> Kenny Millar wrote:
>> I think that will synchronize the input signal?
> It looks like then you will have one FF sync stage. But I'm merely the
> VHDL man... ;-)
>
> BTW:
> When you always get the very same picture, there also may be an
> additional structural flaw in the description.

I do always get the same results, which is why I originally posted here 
- the synchronisation of the input signal may be a red-herring, since 
even with the change I mentioned above, I still get exactly the same 
behaviour.
I will experiment with double-synchronisation, but I think I might still 
see the same behaviour. I'm pretty new to verilog code, so was hoping 
someone here might be able to help me understand why my state machine 
progresses through states 2 to 7 so quickly, and doesn't do what I 
expect - ie stall at each stage until the "dhtin" signal changes.

In the meantime, I will try double-synchronisation and see if that 
helps.

von Lattice User (Guest)


Rate this post
useful
not useful
the initial statement does not belong to the synthesizable subset.
1
initial begin
2
  count = 32'b0;
3
  state = 8'h00; // once only condition
4
  dataBits = 40'd0;
5
  bitCount = 8'd40;
6
  dht_oe = 1'b0;
7
  dataReady = 1'b0;
8
end

If you have it only included to assist with simulation, that is fine. 
But it is then advisable to uses directives to exclude it during 
synthesis.

Starting with verilog 2001 you can use initializers, but check with the 
synthesizer documentation.

Example:
1
reg [7:0] state = 8'h00;

: Edited by Moderator
von Tschaebe (Guest)


Rate this post
useful
not useful
What Lothar wrote about synchronization will definitely hit you (also 
that you are using just a one stage ff).

However, I think there is yet another bug in your code, in line 74, you 
probably meant the inverted input for dhtin instead of the xor operator 
you used, which would be the "~" operator for bitwise operation and "!" 
for a logical not (either one would work in your example)
1
  8'h03: begin // wait for our signal to achieve SPACE AFTER MARK.
2
     if (~dhtin) begin // line 74, was ^dhtin
3
        count =0;

If you want a two stage sync FF you could use something along this line:
1
   reg [1:0] dhtin_sync;
2
   always @(posedge clk) begin
3
      dhtin_sync <= {dhtin_sync[0], dhtin};
4
   end

One last point:
For sequential processes, it is more common to use non blocking 
assignments (as shown above)

Best regards,
Tschaebe

von Kenny M. (kennym)


Rate this post
useful
not useful
Lattice User wrote:
> the initial statement does not belong to the synthesizable subset.
>
>
1
> initial begin
2
>   count = 32'b0;
3
>   state = 8'h00; // once only condition
4
>   dataBits = 40'd0;
5
>   bitCount = 8'd40;
6
>   dht_oe = 1'b0;
7
>   dataReady = 1'b0;
8
> end
9
>
>
> If you have it only included to assist with simulation, that is fine.
> But it is then advisable to uses directives to exclude it during
> synthesis.
>
> Starting with verilog 2001 you can use initializers, but check with the
> synthesizer documentation.
>
> Example:
>
1
> reg [7:0] state = 8'h00;
2
>

OK thanks again.
I now have this for double-synch:
1
reg dhtin, ds1, ds2;
2
always @(posedge clk) begin
3
    ds2<= ds1;
4
    ds1 <= dhtio;
5
    dhtin <= ds2;
6
end

And I know that we go through state 0,1 then 2, otherwise the sensor 
would not talk to us, and that we stall as expected in those states, 
because we are using "count" not the dhtin signal to move forward. But I 
still have it going rapidly from state 2 to 7 when dhtin cannot be 
changing?? I don't understand!

Could it be due to the inout signal? Have I misunderstood how that 
works? I'm using
1
assign dhtio = dht_oe ? 1'b0 " 1b'Z
to tri-state the output when I'm not driving it.

Please forgive my complete newbie-ness!

von Kenny M. (kennym)


Rate this post
useful
not useful
Our posts overlapped - and believe it or not, I was just reading about 
logcal / bitwise operators in the excellen "Introduction to Verilog" and 
had just started wondering if I had the wrong operator.

Let me go fix those things, and I'll get back to you.

von Kenny M. (kennym)


Attached files:

Rate this post
useful
not useful
Thanks again for all your help.
This now works as expected :-)

The problem was indeed the wrong operator (^) instead of (~).
The full code now looks like the attached .v file.

I also changed to double synchronisation, and non-blocking assignments 
and now it is working exactly as expected.

Now to do something useful with the data....

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.