From Hamsterworks Wiki!
Please make sure that you have completed the earlier modules of FPGA course.
Having problems with your code? Do I need to change something? Want a reference solution to the project? Email me at "email@example.com", after removing the "nospam-" bit. I'll try to get back to you in a day or so.
Aims of module
- Receive data send from a PC over RS232 - giving bi-directional communication!
Problems with clock recovery and framing
Synchronising with an incoming signal is usually a hard problem to solve. But for short transfers using low bit rates (like RS232) it is pretty easy to solve by oversampling the incoming signal. Although this isn't the most efficient method it is easy to understand and implement.
If the incoming signal has a bit rate is 9600 baud we will over sample at four times this speed (38400), thus ensuring that for each received bit we will have two good samples.
The next challenge is then to work out which pairs of bits are good, and where a frame starts and ends. Here's my solution.
As discussed in the last module an RS232 frame starts with a Start bit ('L'), has eight data bits and ends with a stop bit ('H'). To receive the data use a 40 bit shift register initialised to '1's, and then capture the incoming signal into the left hand end of a shift register.
After 40 samples we will have the following bits Where '-' is 'don't care' and '??' are pairs of matching 'LL' or 'HH' bits (as they will have been sampled in the sample bit windows):
(MSB) (LSB) -HH--??--??--??--??--??--??--??--??--LL- Stop 7 6 5 4 3 2 1 0 start
If we see this pattern we know have a valid frame, and can then make use of the data
The test to see if we have received a valid frame we need to check the following :
- Check that bits(38 downto 37) = '1'
- Check that bits(34) are bits(33)
- Check that bits(30) are bits(29)
- Check that bits(26) are bits(25)
- Check that bits(22) are bits(21)
- Check that bits(18) are bits(17)
- Check that bits(14) are bits(13)
- Check that bits(10) are bits(9)
- Check that bits(6) are bits(5)
- Check that bits(2 downto 1) are both '0'
If all this is true we can then capture the byte, set a signal to indicate receiving of the byte then reset the shift register back to the empty state, preventing false triggering:
value <= bits(34) & bits(30) & bits(26) & bits(22) & bits(18) & bits(14) & bits(10) & bits(6); byte_received <= '1'; bits <= (others => '1');
Wow - much easier than expected. So what is the catch?
Problems with this solution
The main problem with this solution is that the sending clock and receiving clock must be closely matched. A drift of 2.5% (1/40) in clocks will be enough that the sampling of the start bit and stop bit will be one sample out of step from each other - but will still work with a very 'crisp' signal.
If there is a difference of 5% in timing the first and last sample will be two sample periods out of step, and will never be able to receive the data correctly.
- Create a project that receives characters over RS232 and displays them on the LEDs or seven segment display
- Merge the code from project 16 and 17 to create your own RS232 RX/TX component.
Ready to carry on?
Click here to carry on to the next module.