Reply by YiQi May 29, 20062006-05-29
>1) If the UART received a char (RDA = '1') then goto 2, else goto 1 >2) Read the char from the UART. If the char is ASCII '1' (31h) then >goto 3 else goto 1 >( rdSig <= '1'; if dbOutSig = x"31" then goto 3 ) >3) if the UART's Transmit Buffer is Empty (TBE = '1') then goto 4, else >back to 3 >4) write the 1st char into the UART (wrSig <= '1', dbInSig <= char in >signal X) >5) if the UART's Transmit Buffer is Empty (TBE = '1') then goto 6, else >back to 5 >6) write the 2nd char into the UART >( wrSig <= '1', dbInSig <= char in signal Y ) >DONE
Dave, I could sorry to say your steps won work, It the 1st char won able to send. Because the speed of the FPGA clock is 50MHz and the UART is lot more slow. For this FSM, it is operating in the FPGA clock in 50MHz, while the first char is place into the data bus, and the FSM just into step 5, the UART component still hasn't been update(slow clocking at 9600). The TBE will still in '1', so it will overwrite the 1st char and send the 2nd one. That's why i will need to wait until TBE to '0'. This could be fix by simply adding a condition that until the TBE = '0' then go to step 5, otherwise stay at step 4. What I don't understand is in my code, why I need to have a waitSend state before the initial state of the next char? Sorry... I think I am a "problem kid", questions keep coming up, and I couldn't solve it. Please do help me. ... Thanks YiQi
Reply by YiQi May 29, 20062006-05-29
Thanks Dave.
Yes, you were correct

sorry that i have serval version of this code now, and i even comfuse
myself. as a result, my program is not accroding to the steps.

For rdSig and wrSig, I am reading and writeing at the same time, but I
just ignore the incoming data while i am sending it. Since serial port
using 2 different bus, it should be ok, and it shouldn't effect the
outgoing data.

Let me know if my assumption is wrong.

The send signal is for a process(not shown here) to inform this main
process the X and Y is has change and ready to send it out, that's why
my program start with sending.

Besides these, what are the possiblity that the simulation works
correctly, and after the the design flow, the actual on-chip running
becomes wired? How could I have the simulation close enough to the
on-chip running

Thanks for your advice and help, 
YiQi

Reply by Mr_chips May 23, 20062006-05-23
YiQi wrote:
> Dave, sorry for late reply. > > Here is the code: > entity Main is > Port ( > btn : in std_logic_vector(3 downto 0); > sel : in std_logic_vector(7 downto 0); > > TXD : out std_logic := '1'; > RXD : in std_logic := '1'; > led : out std_logic_vector(7 downto 0); > CLK : in std_logic; > RST : in std_logic := '0'; > ann : out std_logic_vector(3 downto 0); > lcdout : out std_logic_vector(7 downto 0)); > end Main; > > architecture Behavioral of Main is > ------------------------------------------------------------------------ > -- Component Declarations > ------------------------------------------------------------------------ > component UARTcomponent > Port ( > TXD : out std_logic := '1'; > RXD : in std_logic; > CLK : in std_logic; --Master Clock > DBIN : in std_logic_vector (7 downto 0); --Data Bus in > DBOUT : out std_logic_vector (7 downto 0);--Data Bus out > RDA : inout std_logic; --Read Data Available > TBE : inout std_logic := '1'; --Transfer Bus Ready > RD : in std_logic; --Read Strobe > WR : in std_logic; --Write Strobe > PE : out std_logic; --Parity Error Flag > FE : out std_logic; --Frame Error Flag > OE : out std_logic; --Overwrite Error Flag > RST : in std_logic := '0'); --Master Reset > end component; > > > component LCDcomponent > Port ( an3 : out std_logic; > an2 : out std_logic; > an1 : out std_logic; > an0 : out std_logic; > lcddisplay : out std_logic_vector(7 downto 0); > datain : in std_logic_vector(7 downto 0)); > end component; > > ------------------------------------------------------------------------ > -- Local Type Declarations > ------------------------------------------------------------------------ > > type mainState is ( > idle, receive, > initSendX, sendX, waitSendX, > initSendY, sendY, waitSendY); > > -- type sendStates is ( > -- sendX, > -- sendY, > -- sendDir, > -- sendAction, > -- sendIdle); > -- signal sendState, sendNextState : sendStates := sendIdle; > > ------------------------------------------------------------------------ > -- Signal Declarations > ------------------------------------------------------------------------ > signal dbInSig : std_logic_vector(7 downto 0); > signal dbOutSig: std_logic_vector(7 downto 0); > signal rdaSig : std_logic; > signal tbrSig : std_logic; > signal rdSig : std_logic; > signal wrSig : std_logic; > signal peSig : std_logic; > signal feSig : std_logic; > signal oeSig : std_logic; > > signal state : mainState := idle; > signal stNext : mainState; > signal X : std_logic_vector(7 downto 0) := "00110010"; > signal Y : std_logic_vector(7 downto 0) := "00110100"; > signal direction: std_logic_vector(2 downto 0) := "110"; > signal action : std_logic_vector(1 downto 0) := "11"; > > > signal UARTReady : std_logic := '0'; > signal clock : std_logic := '0'; > signal reset : std_logic := '0'; > signal dataReady : std_logic := '0'; > > shared variable send : std_logic := '0'; > > ------------------------------------------------------------------------ > -- Module Implementation > ------------------------------------------------------------------------ > > begin > > > LCD: LCDcomponent port map ( > an3 => ann(3), > an2 => ann(2), > an1 => ann(1), > an0 => ann(0), > lcddisplay => lcdout, > datain => dbOutSig); > > UART: Uartcomponent port map ( > TXD => TXD, > RXD => RXD, > CLK => CLK, > DBIN => dbInSig, > DBOUT=> dbOutSig, > RDA => rdaSig, > TBE => tbrSig, > RD => rdSig, > WR => wrSig, > PE => peSig, > FE => feSig, > OE => oeSig, > RST => RST); > > SET_DATA: process(btn, sel) > begin > if btn(0) = '1' then --reset > reset <= '1'; > dataReady <= '1'; > else > reset <= '0'; > end if; > if btn(2) = '1' then -- set fromX > X <= sel; > dataReady <= '0'; > end if; > if btn(1) = '1' then -- set fromY > Y <= sel; > direction <= "000"; > dataReady <= '0'; > end if; > end process; > > > RUN: process(CLK, UARTready) -- generate the robotcontroller clock > begin > if dataReady = '1' AND UARTready = '1' then > clock <= CLK; > else > clock <= '0'; > end if; > end process; > > process (clock, reset) > variable counter : std_logic_vector(15 downto 0):= > "0000000000000000"; > begin > if (CLK = '1' and CLK'Event) then > if reset = '1' then > send := '0'; > counter := "0000000000000000"; > else > if counter = "1100" then > send := '1'; > else > send := '0'; > end if; > counter := counter + "0000000000000001"; > if counter > "1111111111111110" then > counter := "0000000000000000"; > end if; > end if; > end if; > end process; > > > > process (CLK, RST) > begin > if (CLK = '1' and CLK'Event) then > if RST = '1' then > state <= idle; > else > state <= stNext; > end if; > end if; > end process; > > UART_STATE : process (state, tbrSig, rdaSig, dboutsig, x, y, > direction, action) > variable counter : std_logic_vector(2 downto 0) := "000"; > begin > case state is > > when idle => > led(0) <= '0'; > led(1) <= '1'; > led(2) <= '0'; > led(3) <= '1'; > led(4) <= dbInSig(0); > led(5) <= dbInSig(1); > led(6) <= dbInSig(2); > led(7) <= dbInSig(3); > > rdSig <= '1'; > wrSig <= '0'; > > if send = '1' AND dataReady = '1'then > stNext <= initSendX; > UARTready <= '0'; > else > UARTready <= '1'; > stNext <= idle; > end if; > > when initSendX => > UARTready <= '0'; > > led(0) <= '1'; > led(1) <= '0'; > led(2) <= '1'; > led(3) <= '1'; > led(4) <= '1'; > led(5) <= '1'; > led(6) <= '1'; > led(7) <= '1'; > > rdSig <= '1'; > > dbInSig <= "00110001"; > if tbrSig = '0' then > wrSig <= '0'; > stNext <= sendX; > else > wrSig <= '1'; > stNext <= initSendX; > end if; > > when sendX => > UARTready <= '0'; > > led(0) <= '1'; > led(1) <= '1'; > led(2) <= '0'; > led(3) <= '1'; > led(4) <= '1'; > led(5) <= '1'; > led(6) <= '1'; > led(7) <= '1'; > > dbInSig <= X; --"00110010"; > rdSig <= '1'; > if tbrSig = '1' then > stNext <= waitSendX; > counter := "000"; > wrSig <= '0'; > else > stNext <= sendX; > wrSig <= '0'; > end if; > > when waitSendX => > UARTready <= '0'; > stNext <= initSendY; > > when initSendY => > UARTready <= '0'; > > led(0) <= '1'; > led(1) <= '1'; > led(2) <= '1'; > led(3) <= '0'; > led(4) <= '1'; > led(5) <= '1'; > led(6) <= '1'; > led(7) <= '1'; > > rdSig <= '1'; > dbInSig <= "00110011"; > if tbrSig = '0' then > wrSig <= '0'; --0 > stNext <= sendY; > else > wrSig <= '1'; > stNext <= initSendY; > end if; > > when sendY => > UARTready <= '0'; > > led(0) <= '1'; > led(1) <= '1'; > led(2) <= '1'; > led(3) <= '1'; > led(4) <= '0'; > led(5) <= '1'; > led(6) <= '1'; > led(7) <= '1'; > > dbInSig <= Y; --"00110100"; > rdSig <= '1'; > if tbrSig = '1' then > stNext <= waitSendY; > wrSig <= '0'; > else > stNext <= receive; > wrSig <= '1'; > end if; > > when receive => > > led(0) <= '0'; > led(1) <= '1'; > led(2) <= '1'; > led(3) <= '1'; > led(4) <= '1'; > led(5) <= '1'; > led(6) <= '1'; > led(7) <= '1'; > > rdSig <= '0'; > wrSig <= '0'; > > if rdaSig = '1' then > led(4) <= dbOutSig(0); > led(5) <= dbOutSig(1); > led(6) <= dbOutSig(2); > led(7) <= dbOutSig(3); > > UARTready <= '1'; > stNext <= idle; > else > stNext <= receive; > end if; > > when others => > UARTready <= '0'; > > led(0) <= '1'; > led(1) <= '0'; > led(2) <= '1'; > led(3) <= '0'; > led(4) <= '1'; > led(5) <= '0'; > led(6) <= '1'; > led(7) <= '0'; > > end case; > end process; >
YiQi; In an earlier post you said: I got only only signal from the UART model saying that the transmit bus is empty(TBE) if 1 then empty. Here is what I do step by step: 1. until input arrive, then go to 1 2. read input if input = '1' then go to 3, else back to 1 3. put 'h' on the data bus, wait until TBE is 0 go to 4 4. wait until TBE = 1 then go to 5 5. put 'i' on the data bus, wait until TBE is 0 go to 6 6. wait until TBE = 1 then back to 1 it hang on step 5. wait for TBE to be 0 I would have said: 1) If the UART received a char (RDA = '1') then goto 2, else goto 1 2) Read the char from the UART. If the char is ASCII '1' (31h) then goto 3 else goto 1 ( rdSig <= '1'; if dbOutSig = x"31" then goto 3 ) 3) if the UART's Transmit Buffer is Empty (TBE = '1') then goto 4, else back to 3 4) write the 1st char into the UART (wrSig <= '1', dbInSig <= char in signal X) 5) if the UART's Transmit Buffer is Empty (TBE = '1') then goto 6, else back to 5 6) write the 2nd char into the UART ( wrSig <= '1', dbInSig <= char in signal Y ) DONE I doesn't look like your state-machine follows your step-by-step process. It's sending chars in X and Y and _then_ reading a char from the UART. It also looks like you're reading data from the UART and writing data to the UART at the same time (see state initSendX, where you set both rdSig and wrSig to '1'). I don't see the need for the process that writes into "send". This process is not related or synchronized to anything. HTH -Dave Pollum
Reply by YiQi May 22, 20062006-05-22
the sendY state should be
when sendY =>
                                UARTready <= '0';

                                led(0) <= '1';
                                led(1) <= '1';
                                led(2) <= '1';
                                led(3) <= '1';
                                led(4) <= '0';
                                led(5) <= '1';
                                led(6) <= '1';
                                led(7) <= '1';

                                dbInSig <= Y; --"00110100";
                                rdSig <= '1';
                                if tbrSig = '1' then
                                        stNext <= receive;
<<<<<<<<<<<<<<
                                        wrSig <= '0';
                                else
                                        stNext <= sendY;
<<<<<<<<<<<<<<
                                        wrSig <= '1';
                                end if;

Reply by YiQi May 22, 20062006-05-22
Dave, sorry for late reply.

Here is the code:
entity Main is
	Port (
			 	btn : in std_logic_vector(3 downto 0);
			 	sel : in std_logic_vector(7 downto 0);

		  		TXD	: out std_logic := '1';
		 		RXD	: in std_logic := '1';
		  		led 	: out std_logic_vector(7 downto 0);
		  		CLK	: in std_logic;
		  		RST	: in std_logic	:= '0';
		  		ann 	: out std_logic_vector(3 downto 0);
				lcdout : out std_logic_vector(7 downto 0));
end Main;

architecture Behavioral of Main is
------------------------------------------------------------------------
-- Component Declarations
------------------------------------------------------------------------
component UARTcomponent
   Port (
		 		TXD	 	: out std_logic	:= '1';
		 		RXD 		: in  std_logic;
  		 		CLK 		: in  std_logic;							--Master Clock
		 		DBIN 		: in  std_logic_vector (7 downto 0);	--Data Bus in
		 		DBOUT 	: out std_logic_vector (7 downto 0);--Data Bus out
		 		RDA		: inout std_logic;						--Read Data Available
		 		TBE		: inout std_logic 	:= '1';			--Transfer Bus Ready
		 		RD			: in  std_logic;							--Read Strobe
		 		WR			: in  std_logic;							--Write Strobe
		 		PE			: out std_logic;							--Parity Error Flag
		 		FE			: out std_logic;							--Frame Error Flag
		 		OE			: out std_logic;							--Overwrite Error Flag
		 		RST		: in  std_logic	:= '0');				--Master Reset
end component;


component LCDcomponent
    Port ( an3 : out std_logic;
           an2 : out std_logic;
           an1 : out std_logic;
           an0 : out std_logic;
           lcddisplay : out std_logic_vector(7 downto 0);
           datain : in std_logic_vector(7 downto 0));
end component;

------------------------------------------------------------------------
--  Local Type Declarations
------------------------------------------------------------------------

	type mainState is (
		idle, receive,
		initSendX, sendX, waitSendX,
		initSendY, sendY, waitSendY);

--	type sendStates is (
--		sendX,
--		sendY,
--		sendDir,
--		sendAction,
--		sendIdle);
--	signal sendState, sendNextState : sendStates := sendIdle;

------------------------------------------------------------------------
-- Signal Declarations
------------------------------------------------------------------------
	signal dbInSig	:	std_logic_vector(7 downto 0);
	signal dbOutSig:	std_logic_vector(7 downto 0);
	signal rdaSig	:	std_logic;
	signal tbrSig	:	std_logic;
	signal rdSig	:	std_logic;
	signal wrSig	:	std_logic;
	signal peSig	:	std_logic;
	signal feSig	:	std_logic;
	signal oeSig	:	std_logic;

	signal state	:	mainState := idle;
	signal stNext	:	mainState;
	signal X 		: 	std_logic_vector(7 downto 0) := "00110010";
	signal Y 		: 	std_logic_vector(7 downto 0) := "00110100";
	signal direction: 	std_logic_vector(2 downto 0) := "110";
	signal action	: 	std_logic_vector(1 downto 0) := "11";


	signal UARTReady  : std_logic := '0';
	signal clock		: std_logic := '0';
	signal reset		: std_logic := '0';
	signal dataReady		: std_logic := '0';

	shared variable send : std_logic := '0';

------------------------------------------------------------------------
-- Module Implementation
------------------------------------------------------------------------

begin


LCD: LCDcomponent port map (
						an3 => ann(3),
						an2 => ann(2),
						an1 => ann(1),
						an0 => ann(0),
						lcddisplay => lcdout,
						datain => dbOutSig);

UART: Uartcomponent port map (
						TXD 	=> TXD,
						RXD 	=> RXD,
						CLK 	=> CLK,
						DBIN => dbInSig,
						DBOUT=> dbOutSig,
						RDA	=> rdaSig,
						TBE	=> tbrSig,
						RD	=> rdSig,
						WR	=> wrSig,
						PE	=> peSig,
						FE	=> feSig,
						OE	=> oeSig,
						RST => RST);

	SET_DATA: process(btn, sel)
	begin
		if btn(0) = '1' then --reset
			reset <= '1';
			dataReady <= '1';
		else
			reset <= '0';
		end if;
		if btn(2) = '1' then -- set fromX
			X <= sel;
			dataReady <= '0';
		end if;
		if btn(1) = '1' then -- set fromY
			Y <= sel;
			direction <= "000";
			dataReady <= '0';
		end if;
	end process;


	RUN: process(CLK, UARTready) -- generate the robotcontroller clock
	begin
		if dataReady = '1' AND UARTready = '1' then
			clock <= CLK;
		else
			clock <= '0';
		end if;
	end process;

	process (clock, reset)
		variable counter : std_logic_vector(15 downto 0):=
"0000000000000000";
	begin
		if (CLK = '1' and CLK'Event) then
			if reset = '1' then
				send := '0';
				counter := "0000000000000000";
			else
				if counter = "1100" then
					send := '1';
				else
					send := '0';
				end if;
				counter := counter + "0000000000000001";
				if counter > "1111111111111110" then
					counter := "0000000000000000";
				end if;
			end if;
		end if;
	end process;



	process (CLK, RST)
		begin
			if (CLK = '1' and CLK'Event) then
				if RST = '1' then
					state <= idle;
				else
					state <= stNext;
				end if;
			end if;
		end process;

	UART_STATE : process (state, tbrSig, rdaSig, dboutsig, x, y,
direction, action)
    	variable counter : std_logic_vector(2 downto 0) := "000";
	begin
		case state is

			when idle =>
				led(0) <= '0';
				led(1) <= '1';
				led(2) <= '0';
				led(3) <= '1';
				led(4) <= dbInSig(0);
				led(5) <= dbInSig(1);
				led(6) <= dbInSig(2);
				led(7) <= dbInSig(3);

				rdSig <= '1';
				wrSig <= '0';

				if send = '1' AND dataReady = '1'then
					stNext <= initSendX;
					UARTready <= '0';
				else
					UARTready <= '1';
					stNext <= idle;
				end if;

			when initSendX =>
			 	UARTready <= '0';

				led(0) <= '1';
				led(1) <= '0';
				led(2) <= '1';
				led(3) <= '1';
				led(4) <= '1';
				led(5) <= '1';
				led(6) <= '1';
				led(7) <= '1';

				rdSig <= '1';

				dbInSig <= "00110001";
				if tbrSig = '0' then
					wrSig <= '0';
					stNext <= sendX;
				else
					wrSig <= '1';
					stNext <= initSendX;
				end if;

			when sendX =>
				UARTready <= '0';

				led(0) <= '1';
				led(1) <= '1';
				led(2) <= '0';
				led(3) <= '1';
				led(4) <= '1';
				led(5) <= '1';
				led(6) <= '1';
				led(7) <= '1';

				dbInSig <= X; --"00110010";
				rdSig <= '1';
				if tbrSig = '1' then
					stNext <= waitSendX;
					counter := "000";
					wrSig <= '0';
				else
					stNext <= sendX;
					wrSig <= '0';
				end if;

			when waitSendX =>
				UARTready <= '0';
				stNext <= initSendY;

			when initSendY =>
				UARTready <= '0';

				led(0) <= '1';
				led(1) <= '1';
				led(2) <= '1';
				led(3) <= '0';
				led(4) <= '1';
				led(5) <= '1';
				led(6) <= '1';
				led(7) <= '1';

				rdSig <= '1';
				dbInSig <= "00110011";
				if tbrSig = '0' then
					wrSig <= '0';		  --0
					stNext <= sendY;
				else
					wrSig <= '1';
					stNext <= initSendY;
				end if;

			when sendY =>
				UARTready <= '0';

				led(0) <= '1';
				led(1) <= '1';
				led(2) <= '1';
				led(3) <= '1';
				led(4) <= '0';
				led(5) <= '1';
				led(6) <= '1';
				led(7) <= '1';

				dbInSig <= Y; --"00110100";
				rdSig <= '1';
				if tbrSig = '1' then
					stNext <= waitSendY;
					wrSig <= '0';
				else
					stNext <= receive;
					wrSig <= '1';
				end if;

			when receive =>

				led(0) <= '0';
				led(1) <= '1';
				led(2) <= '1';
				led(3) <= '1';
				led(4) <= '1';
				led(5) <= '1';
				led(6) <= '1';
				led(7) <= '1';

				rdSig <= '0';
				wrSig <= '0';

				if rdaSig = '1' then
					led(4) <= dbOutSig(0);
					led(5) <= dbOutSig(1);
					led(6) <= dbOutSig(2);
					led(7) <= dbOutSig(3);

					UARTready <= '1';
					stNext <= idle;
				else
					stNext <= receive;
				end if;

			when others =>
				UARTready <= '0';

				led(0) <= '1';
				led(1) <= '0';
				led(2) <= '1';
				led(3) <= '0';
				led(4) <= '1';
				led(5) <= '0';
				led(6) <= '1';
				led(7) <= '0';	
				
		end case;
	end process;

Reply by Dave Pollum May 17, 20062006-05-17
YiQi wrote:
> the problem has solved by adding a extra clock cycle between 4 and 5, > but I still don't understand why that will work. Maybe need to wait > longer for sending the byte. If someone know, please tell me. anyway, > > > thanks Mike~!
BTW - In the UARTs I've used (Z8530, 16c450) the UART sets TBE to a 1 when it can accept a byte to be transmitted.
>..I still don't understand why that will work
Without seeing your code it would be difficult to help you. -Dave
Reply by YiQi May 16, 20062006-05-16
the problem has solved by adding a extra clock cycle between 4 and 5,
but I still don't understand why that will work. Maybe need to wait
longer for sending the byte. If someone know, please tell me.  anyway,


thanks Mike~!

Reply by YiQi May 16, 20062006-05-16
by the way, if i go to  1 instead  5 on step 4.  It is working, and it
just a normal echo program

Reply by YiQi May 16, 20062006-05-16
I got only only signal from the UART model saying that the transmit bus
is empty(TBE) if 1 then empty.
Here is what I do step by step:
1. until input arrive, then go to 1
2. read input if input = '1' then go to 3, else back to 1
3. put 'h' on the data bus, wait until TBE is 0 go to 4
4. wait until TBE = 1 then go to 5
5. put 'i' on the data bus, wait until TBE is 0 go to 6
6. wait until TBE = 1 then back to 1

it hang on step 5. wait for TBE to be 0

Reply by May 16, 20062006-05-16
>I am trying to connect my Spartan 3 borad with PC by RS232 , and am >able to echo single input in hyper temial consol. What i am trying to >do is sending "hi" from the board to the pc, by only hit 1 from hyper >termial. Will follow steps design work? I am not sure if the RS232 >(hypertermial) has any limitation on this. I have worked on this for >sevral days, but still doesn't work. any idea will welcome. > >1. read input >2. if input = '1' then go to 3 else back to 1 >3. send 'h' >4. send 'i'
You don't say in what way this isn't working. You may need to wait before step 4 until the hardware is ready to accept another character (if the transmitter has no buffer). That is, you may need to wait until the first character has been transmitted. If you need this "flow control", then the most likely behaviour without it is that only a single character is transmitted (either 'h' or a corrupted character, depending on the behaviour of the transmitter when you write a character to it when it isn't ready).