Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20713 Discussions

RS232 command interpreter vhdl

Altera_Forum
Honored Contributor II
1,315 Views

Hello everyone, I came here in order to find any suggestion for the following issue. 

 

I have a fpga custom board wich needs to make a task depending on the command received by a mcu or pc. For instance, the command <SW> followed by n bytes of data will change the frequency of a DDS system, and so on with other 4 bytes commands (4 ASCII chars). I already have my UART component workin and tested with the windows hyperterminal wich echos back every key pressed. 

 

I tried with a 8bit shift left register and a counter in order to "concatenate" the command and later compare it in order to perform the correspondig action, but I just can't make it work. Does anyone already did something like that before? 

 

the pseudo code is the following 

 

... architecture arch of myEntity is signal RxReady : std_logic; signal enableTx : std_logic; signal cmd : std_logic_vector(31 downto 0) := (others => '0'); signal cmd_tmp : std_logic_vector(31 downto 0) := (others => '0'); signal tmp_data : std_logic_vector(7 downto 0) := (others => '0'); signal cont : integer range 0 to 4 := 0; begin u1 : UART port map (sysclk, sysrst, enableTx, TxD, TxData, RxD, tmp_data, RxReady); process(sysrst, tmp_data, RxReady) begin if sysrst = '1' then enableTx <= '0'; cmd <= (others => '0'); cmd_tmp <= (others => '0'); else if RxReady = '1' then if cont < 4 then cont := cont + 1; cmd_tmp <= cmd_tmp(23 downto 0) & tmd_data; cmd <= cmd_tmp; else cont := 0; end if; else end if; end if; end process; process(cmd) begin -- just a Test, but not working, it only has the last char coming from the PC, i.e, a sequence 1234, should be 1234, but it is just 4444 if cmd = one&two&three&four then outLEDS <= (others => '1'); else outLEDS <= (others => '0'); end if; end process; end architecture; ...  

 

If anyone have a suggestion it will be really appreciated. Thanks in advance.
0 Kudos
2 Replies
Altera_Forum
Honored Contributor II
487 Views

Hi, 

just my two cents... 

You have a mix-up of variable assignment (cont := cont+1) which takes place immediately and signal assignments " <= " which take place "once" the condition is met. Additionally you should synchronize the process for concatenating the command to sysclk rather using the outputflag of the UART process for stringent clock synchronous design... 

Additionally the cont variable increases to 4 (being pure combinatorical, not registered) with the RxReady being '1', not with the rising edge of RxReady indicating a new command being received. 

It may already solve the issue, if you define cont as a signal as well and rewrite the condition from "If RxReady = '1' " to "If Rising_Edge(RxReady)" to envoke these code lines only once for each time you get a new byte by the UART... 

 

Regards, 

Carlhermann
0 Kudos
Altera_Forum
Honored Contributor II
487 Views

Hello Carlhermann, 

 

First of all I want to thank you for your comments and suggestions :o. I was able to solve this issue, part of it was make changes like you suggested before. 

 

 

--- Quote Start ---  

...Additionally you should synchronize the process for concatenating the command to sysclk rather using the outputflag of the UART process for stringent clock synchronous design... 

--- Quote End ---  

 

 

Also I built a FSM for handling the "commands", the code I sure could be improved a lot in order to be more "compact" or efficient; but at least it is working now. 

 

Here's the code 

 

... -- Commands FSM process(sysrst, sysclk, txEnable, rxData) begin if sysrst = '0' then txEnable <= '0'; txData <= (others => '0'); cmd_ctr <= 0; cmd_state <= IDLE; commands <= (others => '0'); elsif sysclk'event and sysclk = '1' then case cmd_state is when IDLE => txEnable <= '0'; txData <= (others => '0'); if rxReady = '1' then cmd_state <= START_CMD; else cmd_state <= IDLE; cmd_rdy <= '0'; cmd_ctr <= 0; commands <= (others => '0'); end if; when START_CMD => case cmd_ctr is when 0 => commands <= commands(23 downto 0) & rxData; cmd_ctr <= 1; cmd_state <= START_CMD; when 1 => if rxReady = '1' then commands <= commands(23 downto 0) & rxData; cmd_ctr <= 2; cmd_state <= START_CMD; end if; when 2 => if rxReady = '1' then commands <= commands(23 downto 0) & rxData; cmd_ctr <= 3; cmd_state <= START_CMD; end if; when 3 => if rxReady = '1' then commands <= commands(23 downto 0) & rxData; cmd_ctr <= 0; cmd_state <= WHICH_CMD; end if; end case; when WHICH_CMD => ...  

 

Thanks again for your support. 

 

Regards, 

 

Efel
0 Kudos
Reply