Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem with initialize transmittion with button

Status
Not open for further replies.

slirenem

Newbie level 6
Joined
Feb 3, 2012
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,388
Hi,

I would like to do that I start transmit via RS232 when I press button. It is part of my code:
Code:
if DBLoad = '0' then --
	Uart_Rdy <= '0'; -- Make sure handshake is immediately busy
	UartFSM <= FSM_Load;
	
else
	
        Uart_Rdy <= '1';
	UartFSM <= FSM_Idle;
						
end if;
but it causes that sending is repeated many times because button is presses -> DBLoad keeps '0'.

I tried to add into the if condition
Code:
and DBLoad'event
but then cannot synthesize. Error messages:

ERROR:Xst:2108 - Logic for signal <Uart_Rdy> is controlled by a clock but does not appear to be a valid sequential description.
ERROR:Xst:1431 - Failed to synthesize unit <uart_transmit>.

Could you give me some suggestion how to deal with it?

EDIT:

I made delay counter before FSM_Load state and it helps. But still would like to know what was wrong in previous solution to avoid such a situations in the future. So please clarify it for me :)
 
Last edited:

Same happend with me yesterday, with mostly same uart project. I founded quite hard to deal with the multiple transmissions, so i rewrote the whole code and based the new code in a state machine.

When button pressed, data loads in after button released, sends it once. I uploaded the code to pastebin: pastebin - Something - post number 2122442

The code is under developement, but works. It's possible to the code sends data in "XX FF" format, where XX is the 8 bits, and FF is "11111111", but i can't see why the FF part is in the transmission, it's can be a packet monitor program bug in PC.

(about the code: written for an Uart-USB modul, with handshake less Uart protocol)
 

How's you goin with your Uart?

Now there is the simplified, warning less, working version of my uart code:

Code:
-- for digilent pmodUSBUart
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all;
     
entity txmit is
port (CLK_IN, START, CTS, RTS : in std_logic ;
		DATA_INPUT : in std_logic_vector(7 downto 0);
		UART_OUT  : out std_logic ) ;
end txmit ;

architecture v1 of txmit is

signal TXD_TEMP_PUFFER: std_logic_vector (7 downto 0);
signal BAUD_CLK  :  std_logic;
signal state :  unsigned (3 downto 0);
type states is (Idle, Transmit, Action); 
signal current_state : states;
signal next_state    : states;
     
begin
tx_states: process (BAUD_CLK, current_state, state)
	begin
		if (rising_edge(BAUD_CLK) ) then
			if (current_state = Transmit) then
				state <= state + "0001" ;
			else
				state <= "0000" ;
			end if;
		end if;
end process;

NEXT_STATE_DECODE: process (CLK_IN, current_state, state, START)
	begin
		if (rising_edge(CLK_IN)) then
			next_state <= current_state;  --default is to stay in current state   
			case (current_state) is
				when Idle =>
					if (START = '1') then
						next_state <= Action;
					end if;
				when Action =>
					if (START = '0') then
						next_state <= Transmit;
					end if;
				when Transmit =>
					if (START = '0' and std_logic_vector(state) = "1101") then
						next_state <= Idle;
					end if;
				when others =>
					next_state <= Idle;
			end case;
		end if;
end process;

BAUD_RATE: process (CLK_IN)
		variable clk_div_counter : integer range 0 to 5208;
	begin   
		if (rising_edge(CLK_IN)) then
			if (clk_div_counter = 5208) then  --50MHz base CLK_IN / 9600baud = 5208,3
				clk_div_counter := 0;   --ISE 13.4 sucks with ranged integer, had to limit it manualy
				BAUD_CLK <= '1';
			else
				clk_div_counter := clk_div_counter + 1;
				BAUD_CLK <= '0';
			end if;
	end if;
End Process;
 
SYNC_PROC: process (CLK_IN)
	begin
		if (rising_edge(CLK_IN)) then
			current_state <= next_state;
		end if;
end process;

Transmit_process : process (BAUD_CLK, current_state, state, DATA_INPUT, CTS, RTS)  -- data format: 1 start bit, 8 data bits, 2 stop bits, no parity bit
	begin
		if (rising_edge(BAUD_CLK) and current_state = Transmit and CTS = '1' and RTS = '1') then
			if (std_logic_vector(state) = "0001") then  --start '0' bit, load input to puffer
				UART_OUT <= '0' ;
				TXD_TEMP_PUFFER <= DATA_INPUT;
			elsif (std_logic_vector(state) >= "0010" and std_logic_vector(state) <= "1010") then  --shift out 8 bits data
				TXD_TEMP_PUFFER <= TXD_TEMP_PUFFER(6 downto 0) & "0" ;
				UART_OUT <= TXD_TEMP_PUFFER(7) ;
			elsif (std_logic_vector(state) = "1011") then   -- number one stop '1' bit
				UART_OUT <= '1';
			elsif   (std_logic_vector(state) = "1100") then	-- number two stop '1' bit
				UART_OUT <= '1';
			end if ;
		end if ;
end process ;
end ;
 
Last edited:

My Upper code was actualy wrong.

Now, there is the better version, tested in Linux terminal. Previous testing under Windows was a bad idea, it handles CTS and RTS signals badley which gaves me fals results.

This is the 2*12bit version of the code, which makes it easy to test with Digilent's pmods. (easy to modify)

Code:
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all;
     
entity txmit is
port (CLK_IN, START, CTS, RTS : in std_logic ;
		DATA_INPUT_0, DATA_INPUT_1 : in std_logic_vector(11 downto 0);
		UART_OUT  : out std_logic ) ;
end txmit ;

architecture v1 of txmit is  --For Digilent PmodUSBUart

signal TXD_TEMP_PUFFER: std_logic_vector (7 downto 0);
signal BAUD_CLK  :  std_logic;
signal state :  unsigned (5 downto 0);
type states is (Idle, Transmit, Loaddata); 
signal current_state : states;
signal next_state    : states;
     
begin
tx_states: process (BAUD_CLK, current_state, state)
	begin
		if (rising_edge(BAUD_CLK) ) then
			if (current_state = Transmit) then
				state <= state + "000001" ;
			else
				state <= "000000" ;
			end if;
		end if;
end process;

NEXT_STATE_DECODE: process (CLK_IN, current_state, state, START)
	begin
		if (rising_edge(CLK_IN)) then
			next_state <= current_state;  --default is to stay in current state   
			case (current_state) is
				when Idle =>
					if (START = '1') then
						next_state <= Loaddata;
					end if;
				when Loaddata =>
					if (START = '0') then
						next_state <= Transmit;
					end if;
				when Transmit =>
					if (START = '0' and std_logic_vector(state) = "110001") then
						next_state <= Idle;
					end if;
				when others =>
					next_state <= Idle;
			end case;
		end if;
end process;

BAUD_RATE: process (CLK_IN)
		variable clk_div_counter : integer range 0 to 5208;
	begin   
		if (rising_edge(CLK_IN)) then
			if (clk_div_counter = 5208) then  --50MHz base CLK_IN / 9600baud = 5208,3
				clk_div_counter := 0;   --ISE 13.4 sucks with ranged integer, had to limit it manualy
				BAUD_CLK <= '1';
			else
				clk_div_counter := clk_div_counter + 1;
				BAUD_CLK <= '0';
			end if;
	end if;
End Process;
 
SYNC_PROC: process (CLK_IN)
	begin
		if (rising_edge(CLK_IN)) then
			current_state <= next_state;
		end if;
end process;

Transmit_process : process (BAUD_CLK, current_state, state, DATA_INPUT_0, DATA_INPUT_1, CTS, RTS)  -- data format: 1 start bit, 8 data bits, 2 stop bits, no parity bit, LSB first
	begin
		if (rising_edge(BAUD_CLK) and current_state = Transmit and RTS = '0' and CTS = '1' ) then  --CTS = '1' and RTS = '0' means the reciever is waiting for transmission
			if (std_logic_vector(state) = "000001") then  --start '0' bit, load input to puffer
				UART_OUT <= '0' ;
				TXD_TEMP_PUFFER <= DATA_INPUT_0(7 downto 0);
			elsif (std_logic_vector(state) >= "000010" and std_logic_vector(state) <= "001000") then  --shift out 8 bits data
				UART_OUT <= TXD_TEMP_PUFFER(0);
				TXD_TEMP_PUFFER <= "0" & TXD_TEMP_PUFFER(7 downto 1);
			elsif (std_logic_vector(state) = "001001") then
				UART_OUT <= TXD_TEMP_PUFFER(0) ;
			elsif (std_logic_vector(state) = "001010") then   -- number one stop '1' bit
				UART_OUT <= '1';
			elsif   (std_logic_vector(state) = "001011") then	-- number two stop '1' bit
				UART_OUT <= '1';
			-----------------------------------------------------------------------------------------------
			elsif (std_logic_vector(state) = "001100") then  --start '0' bit, load input to puffer
				UART_OUT <= '0';
				TXD_TEMP_PUFFER <= "0000" & DATA_INPUT_0(11 downto 8);
			elsif (std_logic_vector(state) >= "001101" and std_logic_vector(state) <= "010011") then  --shift out 8 bits data
				UART_OUT <= TXD_TEMP_PUFFER(0);
				TXD_TEMP_PUFFER <= "0" & TXD_TEMP_PUFFER(7 downto 1);
			elsif (std_logic_vector(state) = "010100") then
				UART_OUT <= TXD_TEMP_PUFFER(0);
			elsif (std_logic_vector(state) = "010101") then   -- number one stop '1' bit
				UART_OUT <= '1';
			elsif   (std_logic_vector(state) = "010110") then	-- number two stop '1' bit
				UART_OUT <= '1';
			-----------------------------------------------------------------------------------------------
			elsif (std_logic_vector(state) = "010111") then  --start '0' bit, load input to puffer
				UART_OUT <= '0';
				TXD_TEMP_PUFFER <= DATA_INPUT_1(7 downto 0);
			elsif (std_logic_vector(state) >= "011000" and std_logic_vector(state) <= "011110") then  --shift out 8 bits data
				UART_OUT <= TXD_TEMP_PUFFER(0);
				TXD_TEMP_PUFFER <= "0" & TXD_TEMP_PUFFER(7 downto 1);
			elsif (std_logic_vector(state) = "011111") then
				UART_OUT <= TXD_TEMP_PUFFER(0);
			elsif (std_logic_vector(state) = "100000") then   -- number one stop '1' bit
				UART_OUT <= '1';
			elsif   (std_logic_vector(state) = "100001") then	-- number two stop '1' bit
				UART_OUT <= '1';
			-----------------------------------------------------------------------------------------------
			elsif (std_logic_vector(state) = "100010") then  --start '0' bit, load input to puffer
				UART_OUT <= '0' ;
				TXD_TEMP_PUFFER <= "0000" & DATA_INPUT_1(11 downto 8);
			elsif (std_logic_vector(state) >= "100011" and std_logic_vector(state) <= "101001") then  --shift out 8 bits data
				UART_OUT <= TXD_TEMP_PUFFER(0);
				TXD_TEMP_PUFFER <= "0" & TXD_TEMP_PUFFER(7 downto 1);
			elsif (std_logic_vector(state) = "101010") then
				UART_OUT <= TXD_TEMP_PUFFER(0);
			elsif (std_logic_vector(state) = "101011") then   -- number one stop '1' bit
				UART_OUT <= '1';
			elsif   (std_logic_vector(state) = "101100") then	-- number two stop '1' bit
				UART_OUT <= '1';
			else
				UART_OUT <= '1';
			end if ;
		end if ;
end process ;
end ;

Testing in Linux terminal:

If the device working correctly, it will be present somewhere in /dev/tty... In my case, this device is /dev/ttyUSB0

"#" means u will need root privilages
Set up connection:
Code:
#stty -F /dev/ttyUSB0 9600 cread crtscts cs8 -cstopb -parenb
--see stty man page for details.

Reading data:
Code:
#od -An -d -N4 /dev/ttyUSB0


-d means u want see data in decimal values
-N4 means the "od" will wait for 4 * 8 bits of data.
 

Hi,

I would like to do that I start transmit via RS232 when I press button. It is part of my code:
Code:
if DBLoad = '0' then --
	Uart_Rdy <= '0'; -- Make sure handshake is immediately busy
	UartFSM <= FSM_Load;
	
else
	
        Uart_Rdy <= '1';
	UartFSM <= FSM_Idle;
						
end if;
but it causes that sending is repeated many times because button is presses -> DBLoad keeps '0'.

I tried to add into the if condition
Code:
and DBLoad'event
but then cannot synthesize. Error messages:



Could you give me some suggestion how to deal with it?

EDIT:

I made delay counter before FSM_Load state and it helps. But still would like to know what was wrong in previous solution to avoid such a situations in the future. So please clarify it for me :)

Pressing the button logic must be designed properly. Use one shot logic like this, so that you will only capture the pulse once for every press and release.
Code:
process(clk)
begin
   if rising_edge (clk) then
      if (reset  = '1') then
         Q1 <= '0';
         Q2 <= '0';
         Q3 <= '0'; 
      else
         Q1 <= Key_IP;
         Q2 <= Q1;
         Q3 <= Q2;
      end if;
   end if;
end process;
 
Key_OP <= Q1 and Q2 and (not Q3);
Use the above logic. You will not have multiple triggers....
I hope your UART code is correct in other cases...
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top