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.

Reading and sending multiple bytes through UART in VHDL

Status
Not open for further replies.

Feco

Newbie level 6
Joined
May 13, 2013
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,371
Hello.
I made a simple UART module (receive and send) in VHDL for my Spartan 6 (Nexys 3) FPGA.
That module reads multiple bytes, stores them, then sends back. If I do it with 4-8 bytes theres is no problem, BUT if I increase the byte number, it randomly keeps crushing and stops working. I have no idea why.

bigger data size --- bigger chance to crush
lower data size --- lower chance to crush (or no crush at all)

Someone could point out what is the problem?

The code:

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity uart is
    Port ( RX  : in  STD_LOGIC;
           TX  : out  STD_LOGIC;
           CLK : in  STD_LOGIC);
end uart;

architecture Behavioral of uart is

constant max : integer := (100000000/(2*9600))-1; 
signal CLK_9600 : STD_LOGIC;
signal CLK_cnt : integer range 0 to max := 0;

type state is (start, s0, s1, s2, s3, s4, s5, s6, s7, stop);
signal current_state_rec : state;
signal next_state_rec : state;
signal current_state_snd : state;
signal next_state_snd : state;

type matrix_1 is array (0 to 19) of STD_LOGIC_VECTOR(7 downto 0);
type matrix_2 is array (0 to 19) of STD_LOGIC_VECTOR(7 downto 0);
signal memory_in : matrix_1;
signal memory_out : matrix_2;
signal akku_vector : STD_LOGIC_VECTOR(7 downto 0);

signal rec_complete_flag : STD_LOGIC;
signal snd_complete_flag : STD_LOGIC;
signal memory_full_flag : STD_LOGIC;

signal write_address : integer range 0 to 19;
signal read_address : integer range 0 to 19;

begin

memory_out <= memory_in;

process(CLK)
begin
	if rising_edge(CLK) then
		if CLK_cnt = max then
			CLK_cnt <= 0;
			CLK_9600 <= not(CLK_9600);
		else
			CLK_cnt <= CLK_cnt + 1;
		end if;
	end if;
end process;

process(CLK_9600)
begin 
	if rising_edge(CLK_9600) then
		current_state_rec <= next_state_rec;
		current_state_snd <= next_state_snd;
		akku_vector <= RX & akku_vector(7 downto 1);
	end if;
end process;

process(rec_complete_flag, CLK_9600)
begin
	if rec_complete_flag = '1' and rising_edge(CLK_9600) then
		if write_address = 19 then
			write_address <= 0;
			memory_full_flag <= '1';
			memory_in(write_address) <= akku_vector;
		else
			write_address <= write_address + 1;
			memory_full_flag <= '0';
			memory_in(write_address) <= akku_vector;
		end if;
	end if;
end process;

process(snd_complete_flag, CLK_9600)
begin
	if snd_complete_flag = '1' and rising_edge(CLK_9600) then
		if read_address = 19 then
			read_address <= 0;
		else
			read_address <= read_address + 1;
		end if;
	end if;
end process;

process(RX, current_state_rec)
begin
	case current_state_rec is
		when start =>
			if RX = '0' then
				next_state_rec <= s0;
			else
				next_state_rec <= start;
			end if;
			rec_complete_flag <= '0';
		when s0 =>
			next_state_rec <= s1;
			rec_complete_flag <= '0';
		when s1 =>
			next_state_rec <= s2;
			rec_complete_flag <= '0';
		when s2 =>
			next_state_rec <= s3;
			rec_complete_flag <= '0';
		when s3 =>
			next_state_rec <= s4;
			rec_complete_flag <= '0';
		when s4 =>
			next_state_rec <= s5;
			rec_complete_flag <= '0';
		when s5 =>
			next_state_rec <= s6;
			rec_complete_flag <= '0';
		when s6 =>
			next_state_rec <= s7;
			rec_complete_flag <= '0';
		when s7 =>
			next_state_rec <= stop;
			rec_complete_flag <= '0';
		when others =>
			next_state_rec <= start;
			rec_complete_flag <= '1';
		end case;
end process;

process(memory_full_flag, current_state_snd, read_address, memory_out)
begin
	case current_state_snd is
		when start =>
			if memory_full_flag = '1' then
				next_state_snd <= s0;
				TX <= '0';
			else
				next_state_snd <= start;
				TX <= '1';
			end if;
			snd_complete_flag <= '0';
		when s0 =>
			next_state_snd <= s1;
			TX <= memory_out(read_address)(0);
			snd_complete_flag <= '0';
		when s1 =>
			next_state_snd <= s2;
			TX <= memory_out(read_address)(1);
			snd_complete_flag <= '0';
		when s2 =>
			next_state_snd <= s3;
			TX <= memory_out(read_address)(2);
			snd_complete_flag <= '0';
		when s3 =>
			next_state_snd <= s4;
			TX <= memory_out(read_address)(3);
			snd_complete_flag <= '0';
		when s4 =>
			next_state_snd <= s5;
			TX <= memory_out(read_address)(4);
			snd_complete_flag <= '0';
		when s5 =>
			next_state_snd <= s6;
			TX <= memory_out(read_address)(5);
			snd_complete_flag <= '0';
		when s6 =>
			next_state_snd <= s7;
			TX <= memory_out(read_address)(6);
			snd_complete_flag <= '0';
		when s7 =>
			next_state_snd <= stop;
			TX <= memory_out(read_address)(7);
			snd_complete_flag <= '0';
		when others =>
			if (read_address = 19) and (memory_full_flag = '1') then
				next_state_snd <= stop;
				snd_complete_flag <= '0';
			else
				next_state_snd <= start;
				snd_complete_flag <= '1';
			end if;
			TX <= '1';
		end case;
end process;

end Behavioral;

Thanks for your help.
 

Well there are issues with the fact you have logic generated clocks and potentially gated clocks. These are poor practice in FPGAs. you should generate a clock enable and use the system clock for all registers.

You have a syntax error:
memory_out <= memory_in;

is wrong, as they are different types. If you had simulated this it would not have compiled (I dont trust ISE, its vhdl compiler is not the best).

Have you written a testbench for this? did you debug it and put in multiple data values?
 

You have a syntax error:
memory_out <= memory_in;

Oh yeah, memory_out should be matrix_1 too. I tested, if I could send back different data, but forgot to change back.

Have you written a testbench for this? did you debug it and put in multiple data values?

The simulator in ISE doesn't work under win8.1 so I cannot do it. I also tried Symphony EDA at the beginning but it just gives me a constant '1' on TX.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top