Hi everyone! I'm a starter in VHDL and I'm using Xilinx's Spartan 3E for some data conversion (A/D) and transmission to computer by RS232 protocol. The A/D converter has a 12 bit output but the UART controller can only transmit 8 bits. So I was thinking that I could write a VHDL module that would "split" the 12 bits in two 8 bit long segments (the last 8 LSB and the first 4 MSB padded with zeros). Because I have to implement some digital filters too in a later moment, I'd like to transmit 6 packs of 8 bits to the UART controller, each pack after the current pack is shifted out of the shift register from the UART controller. So far, I have made an entity using state machines, but it doesn't seem to work. I have attached the source code. Can anybody help me to resolve this issue? Thanks in advance!
> use IEEE.STD_LOGIC_ARITH.ALL; > use IEEE.STD_LOGIC_UNSIGNED.ALL; > signal dataCounter: STD_LOGIC_VECTOR(2 downto 0) := "000"; > dataCounter <= dataCounter + '1'; You should use the numeric_std and its datatypes unsigned and signed for doing calculations on a vector... > if (RFD = '1' and RFD'event) then This will never work reliably in real world. A synchronous is defined by having only 1 clock source: the one and only FPGA clock. > sync_proc: process(CLK, RST) > begin > if (CLK'event and CLK = '1') then > if (RST = '1') then 1. Theres no need for the RST signal in the sensitivity list. The clock is the onbly signal responsible for a change in this process 2. What about using rising_edge() instead of the incomplete 'event and '1' 3. Why do you need a reset at all? > So far, I have made an entity using state machines, but it doesn't > seem to work. How do you see this? Do you run a simulation? Or do you just try it on hardware?
Thank you for the suggestions! I am using a reset because I have resets on all other entities in the whole system and in this entity the dataCounter needs a reset too. Instead of
if (RFD = '1' and RFD'event) then
what should I use to increment the dataCounter? I have simulated and tried the system physically too. When I'm doing the simulation, the dataCounter is not incremented at all it gets "00X" then it goes to "XXX" after a while (after changing RFD). When trying out for real, there are times when the serial port receives data, and there are times when it gets some, but absolutely in a chaotic way.
> Thank you for the suggestions! I am using a reset because > I have resets on all other entities in the whole system This is no good design practice. Read the the Xilinx whitepaper 272... > and in this entity the dataCounter needs a reset too. No. It doesn't. This is no logic inference and also no finally reason. A reset does not become good because you use it everywhere. The only thing that scores for you: its written that way in almost every book about VHDL... And because VHDL /= FPGA that means: most VHDL books are bad FPGA books. However: > I have simulated and tried the system physically too. When I'm doing the > simulation, the dataCounter is not incremented at all it gets "00X" then > it goes to "XXX" after a while (after changing RFD) So go and solve the collision (='X'). Look at this:
dataCounter <= dataCounter + '1'; --- first process
if (current_state = Init) then
enDataCounter <= '0';
dataCounter <= "000"; --- second process
Two processes driving one signal. That must result in a collision... > When trying out for real, there are times when the serial port > receives data, and there are > times when it gets some, but absolutely in a chaotic way. How many clocks do you have in your design? A hint: a clock signal is every signal with a 'event behind it. > what should I use to increment the dataCounter? Use this state: next_state <= Output; In the state Output you increment the dataCounter with the "one and only" FPGA CLK.
I have solved now the existing collision. I have only one true clock, the CLK signal which is the FPGA clock. I will try out the configuration tomorrow in the lab, so far in ModelSim it works. Thank you for the help!
> I have only one true clock, So, only this "true" clock has to appear with a 'event (or rising_edge or falling_edge) statement. Because the synthesizer will create (lokal) clocks for every other signal related to such a statement. > so far in ModelSim it works. Yes of course. Also e.g. wait for 20 ms works in the simulator. But (todays) theres no chance for this in hardware...
I have made several tests today with the hardware configuration and my design doesn't work at all. In Modelsim everything just works fine, but there is some kind of problem when trying to send the 12 bits of the ADC to the RS232 controller. I think the source of the problem is the bad synchronization of the splitter entity with the other entities (the ADC controller and the RS232 controller). I have tested the other two entities separately and they're working just fine, so I'm sure that the splitter does something wrong - but I can't figure out what. I have attached the files from my project, maybe you can enlighten my mind. Thank you!
Does your RS232 itself work? Did you check to send a character from the PC, loop it back inside the FPGA and send it back to the PC. I had a look after the rs232 module. I had to sroll up and down (because its so incredibly long). And whats that? THREE clocks... :-o
if CLK = '1' and CLK'Event then
if rClk = '1' and rClk'Event then
if (tClk = '1' and tClk'event) then
So dont ask why your design isn't working in reality... There is a small set of rules:
A VHDL desgin (particularly a starters design) must have exactly 1 clock.
This clock is active on the same edge always (rising or falling).
There is no (and specially no asynchronous and/or combinatorial) reset.
Every external signal must be clocked into the FPGA using 2 flipflop stages.
For every deviation from the rules above you must have compelling evidence
and be able to eplain thoroughly why e.g. you need two clocks.
If you can sat "Yes, I've done that" to every single statement, then your design will work. BTW: Have a look for my RS232 Module. The comments are German, but you will have an overview almost immediately: http://www.lothar-miller.de/s9y/categories/42-RS232
Thank you for the kind answer! Unfortunately I thought all over again, and concluded that serial communication was the worst thing I could think of, given the fact that the ADC works with approximately 780 KHz sampling frequency, the speed of the serial port was way too slow - so I need to look after another solution. Anyhow, your tips were very useful, I couldn't read them in the books I own - and I think I'm starting to understand that simplicity is the keyword in digital design with FPGAs.
> understand that simplicity is the > keyword in digital design with FPGAs. Yes it is. Because the only parts you have inside the FPGA are LUTs and flipflops...