Author Topic: Verilog - RS-232 receiver - Randomly Halts  (Read 3122 times)

0 Members and 1 Guest are viewing this topic.

Offline pigtwoTopic starter

  • Regular Contributor
  • *
  • Posts: 133
Verilog - RS-232 receiver - Randomly Halts
« on: January 31, 2016, 10:53:44 pm »
Hello all,

I'm working on a basic RS-232 receiver to work with the basic FTDI usb converter.  I've got it to work but I've run into a weird problem.  It works perfectly for single reads, but if I have it read a bunch of times(not in a row, maybe a few millisecond gap between data being sent) it will just stop working.  The weird part about this is it seems to be random.  The number of reads until it breaks is probably 50-100.  And the state the it breaks in is seemingly random. 

*code below for reference.

It's kind of hard to describe what I mean by it breaking.  It's like it just becomes completely unresponsive.  Data comes into the RX line but it never responds.  So you would think it's just stuck in some state, but I fairly thoroughly tested to see what state it was getting stuck in but I can't tell.  What I did was make an test output and have it assert when it's in that state.  This gave me completely random results.  It was almost like, if I asserted the test output in a state, it would never fail in that state.  I could never get it to consistently fail on a state.  Then to make things weirder if if I have it assert in some states it will actually start working completely.  But then other states it won't work.  Which doesn't really make sense.  This test output isn't connected to anything, it just goes high or low and I look at it on a logic analyzer. 

I know I've given a lot of information but I guess that's because it's very random and I can't see the pattern here.  For example, if I remove a state that essentially has it wait for the stop bit to pass, it will actually work.  The problem with this is that depending on what the last data bit is, it might confuse it for the start bit and start an invalid read.  But I can't see why this is, it all seems random. 

Ok here's the code.  There's a major design flaw so I'm going to rewrite it but I'm just very curious about what would cause this.  Also I simulated and it does not exhibit this problem. 

This code is the RS-232 receiver.  It works by checking the RX line for the start bit every cycle, so that it doesn't miss it.  Then the rest is just handshaking to give the data to the module that wants it.  It's not complete because I ran into this problem.

http://pastebin.com/Hrgkjb2r

For reference the module that is driving this one is here.  It pretty much just takes the data from it then outputs it to some LEDs. 

http://pastebin.com/dCeREk3v

Any suggestions or thought would be great.  I'm very curious about what could cause this because with my limited understanding I don't know of anything that could. 
 

Offline miguelvp

  • Super Contributor
  • ***
  • Posts: 5550
  • Country: us
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #1 on: January 31, 2016, 11:02:11 pm »
Is this on windows?

If so you might want to check your FTDI USB/UART is not a fake chip:
https://www.eevblog.com/forum/microcontrollers/ftdi-gate-2-0/
 

Offline pigtwoTopic starter

  • Regular Contributor
  • *
  • Posts: 133
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #2 on: January 31, 2016, 11:14:17 pm »
It is on windows, but the data coming out of the ftdi chip is correct.  If I understood that thread correctly if it thinks it's fake it just outputs random data, which mine isn't doing. 
 

Offline c4757p

  • Super Contributor
  • ***
  • Posts: 7799
  • Country: us
  • adieu
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #3 on: January 31, 2016, 11:19:24 pm »
Have you simulated your design and tested it there?
No longer active here - try the IRC channel if you just can't be without me :)
 

Offline pigtwoTopic starter

  • Regular Contributor
  • *
  • Posts: 133
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #4 on: January 31, 2016, 11:27:36 pm »
Yeah I tried simulating and it doesn't show this problem.  The simulation is different in that the data on the real fpga comes in kind of randomly but in the simulation I had it come in consistently.  I didn't try putting gaps in the data like there is in the real design, so maybe I'll try that. 
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #5 on: February 01, 2016, 12:07:02 am »
I had a quick look, and didn't see anything obvious, but the logic is a bit more involved than I usually use for RS232/serial in my hacks

However - MAKE SURE YOU SYNCHRONIZE YOUR RX SIGNAL  :)

e.g.

  always @(posedge CLOCK_50)
  begin
     rx_safe_to_use                   <= rx_not_quite_safe_to_use
     rx_not_quite_safe_to_use  <= RX;
  end

And NEVER use RX anywhere else in your design's logic. (Verilog is all foreign to me, so excuse my poor code!)

Also - 50MHz clock, 3MHz data rate... um... 16.666 cycles per bit?

I would not use a FSM, and instead use something bomb-proof (in very bad pseudo code)
Code: [Select]
every clock cycle
   when counter = 1.5*50/3 shift in bit 0
   when counter = 2.5*50/3 shift in bit 1
   when counter = 3.5*50/3 shift in bit 2
   when counter = 4.5*50/3 shift in bit 3
   when counter = 5.5*50/3 shift in bit 4
   when counter = 6.5*50/3 shift in bit 5
   when counter = 7.5*50/3 shift in bit 6
   when counter = 8.5*50/3 shift in bit 7 and assert de
 
   if counter = 9.5*50/3 then
      (((waiting for start bit)))
      if rx_safe_to_use = '0' then
       counter = 0
     else
   else
     counter <= counter + 1;
   end if;

Using 50 because the design's clock is 50 MHz and 3 because the serial data rate is 3 Mb/s. Because of the high data rate counter only needs to be an 8 bit counter, so it isn't too fugly.
« Last Edit: February 01, 2016, 08:58:24 am by hamster_nz »
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline kc8apf

  • Regular Contributor
  • *
  • Posts: 103
  • Country: us
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #6 on: February 01, 2016, 12:22:18 am »
Why did you put all of your logic in a combinatorial section?  As hamster_nz said, in the behavioral section, synchronize the RX and look for edges:

always @(posedge CLOCK_50) begin
  rx_d1 <= rx;
  rx_d2 <= rx_d1;

  if (rx_d1 & ~rx_d2) begin  # Found an RX positive edge
    # If in Idle, move to Start.
  end
end

Usually you look for the edge of the start bit and then start a counter that runs off the system clock (CLOCK_50).  Figure out how many CLOCK_50 ticks will happen per RX bit.  When the counter hits that value, sample the RX input and reset the counter.  Repeat until all the bits have been read.
 

Offline pigtwoTopic starter

  • Regular Contributor
  • *
  • Posts: 133
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #7 on: February 01, 2016, 01:04:45 am »
You guys were right, it was me not synchronizing the RX line.  I literally just read about this too.  I am surprised by the result though, I thought it would just oscillate between one and zero for a while but eventually would settle (whether it would settle correctly would be random).   

@hamster_nz
You're right my design is a little complicated.  The problem I ran into was how to always watch for the start bit but also feed the received data out. 

In you're psudo code you say "when counter = 1.5*50/3".  For the 1.5*50/3, would I just round this to the closest integer?  Or would actually be like a float?

@kc8apf
I did it like that because that's the way my book taught me but I've really been meaning to learn how to use sequential logic better.  I kind of just use it to create flip-flops for the registers then do all the real work with combinational logic.  This is a good example of how the way I'm doing it is bad. 

Thanks for the help!

« Last Edit: February 01, 2016, 01:06:47 am by pigtwo »
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #8 on: February 01, 2016, 01:39:24 am »
You guys were right, it was me not synchronizing the RX line.  I literally just read about this too.  I am surprised by the result though, I thought it would just oscillate between one and zero for a while but eventually would settle (whether it would settle correctly would be random).   

Yeah, and what you are reading is most likely be  incorrect too. It will waffle on about metastability, but that isn't the cause of your problem.

Your design uses that signal as the same asynchronous input to more than once - let's just say it is used to reset a multi-bit counter to zero.

From the pin, the signal might make the 'closest' bit of the counter in 5.00ns, and to the 'furthest' bit of the counter in 5.05ns. If your design clocks at 50 MHz (20ns) That gives a 0.05ns /20.0ns  = 1 in 400 chance that the two parts of the design are seeing the signal as having different values each time the RX signal transitions. Enough to get a few characters through, but not a long stream.

If it was a true metastability error it would more likely be a one-in-a-billion event (e.g. once every 20 seconds or so (or even longer) at 50 MHz), especially with a relatively slow design as the 20ns cycle gices a lot of time for a flipflop to snap to a stable state.

I've run an experiments with an async 50 MHz signals into a 200 MHz clock domain, and I had to wait hours for any metastability events to be seen.







@hamster_nz
In you're psudo code you say "when counter = 1.5*50/3".  For the 1.5*50/3, would I just round this to the closest integer?  Or would actually be like a float?

Yep, just round down to the closet integer. It might be more technically correct to subtract one also, but hey! you've got sixteen or so clock edges per bit, so being off by one or two isn't going to break it. :-)
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline kc8apf

  • Regular Contributor
  • *
  • Posts: 103
  • Country: us
Re: Verilog - RS-232 receiver - Randomly Halts
« Reply #9 on: February 01, 2016, 04:21:27 am »
Alternatively, you could use a phase accumulator for better jitter.  Conceptually, you want to create a clock running at the baud rate.  When the start bit shows up, you enable the clock and use its edges to read RX.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf