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.

Need some quick help with VHDL

Status
Not open for further replies.

Plecto

Full Member level 5
Joined
Jan 4, 2012
Messages
315
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,298
Activity points
4,979
I'm trying to implement a UART on a FPGA. The data that are coming in are saved in 32-bit registers, but I'm having trouble accessing each individual bit in these registers. I would like to implement somthing like this:

signal bitnumber : STD_LOGIC_VECTOR(4 DOWNTO 0);
signal D_OUT : STD_LOGIC_VECTOR(31 DOWNTO 0);
signal RX : ST_LOGIC;

process (clock)
begin
if rising_edge (clock) then
bitnumber <= bitnumber + 1;
D_OUT(bitnumber) <= RX;
end if;
end process;

This is just a part of the code, I'm only trying to emphasize having a signal inside the parantheis of another signal (D_OUT(bitnumber)), but this is not possible. I don't want to make 32 if statements to be able to access each of the 32 bits, there has to be a way to do this more easily?
 

it would be easier if you declared bitnumber as an unsigned, then you wouldnt get errors in the arithmatic and then could easily cast it to an integer to do the bit lookup. Unsigned is decalred in the numeric_std library (std_logic_arith, std_logic_unsigned and std_logic_signed are NOT standard VHDL libraries).


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use ieee.numeric_std.all;
 
...
 
signal bitnumber : unsigned(4 downto 0) := (others => '0');  --otherwise simulation wont work. Alternativly, use a reset
signal D_OUT : STD_LOGIC_VECTOR(31 DOWNTO 0);
signal RX : ST_LOGIC;
 
process (clock)
begin
  if rising_edge (clock) then
    D_OUT( to_integer(bitnumber) ) <= RX;
 
    bitnumber <= bitnumber + 1;
    
  end if;
end process;

 

I don't exactly understand which coding problem you address in your post. Using VHDL standard libraries, bitnumber must be converted to integer to be used as index.

In terms of resource utilization, a shift register will be probably better.
 

That worked, TrickyDicky, thank you :) I'm wondering what the difference between STD_LOGIC_VECTOR and UNSIGNED is though? What if I want to do something like this:

signal integer : STD_LOGIC;

if (integer = '1') then
something = something_else + 1;
integer = '0';
end if;

I understand why this doesn't work, it checks the value of "integer" at the same time as it tries to write it to zero. I do want a way to only enter a IF-statement once though, but I'm not sure how to accomplish that.
 

Its all to do with VHDL strong typing. A std_logic_vector was intended to be a bag-o-bits, not a numeric representation. The unsigned type is also an array of std_logic, but it is meant to represent an unsigned number. There is a similar signed type.

The problem with using std_logic_vector as a number is that it isnt clear whether it's a signed or unsigned vector. Synopsys wrote some packages to handle them as numbers in the early 90s (std_logic_unsigned/signed) and other vendors wrote their own versions. They became a defacto standard, but were never updated or adopted officially into the VHDL standard. And unfortunately there are lots of old textbooks around that teach their use, and old professors and engineers still use them because they havent changed in 20 years!

numeric_std became part of the language in 1993. It defines signed and unsigned types. They are closely related to std_logic_vector as they are all arrays of std logic, so type casting is easy.

Now, looking at your code, it looks like you're thinking a bit like a software engineer. For a start, the syntax is all wrong, and I wouldnt recommend calling a signal "integer" as it is a base type. You need to think in terms of hardware, not code. What hardware are you trying to acheive? this is a hardware description language after all.
 

The only experience I have is with C an microcontrollers. While I do understand that this is a hardware description language and that everything is happening in parallel (not sequential as with a programming language) I still find it hard to understand how some things compile while other pieces of code don't compile. I do my best to picture my code being a direct representation of a bunch of logic gates connected together, I assume that this is a correct way of picturing what's happening? I must say that it's far easier programming a MCU where I know that each line of code is executed after the previous one :p

I'm currently working on a UART (just handling the receiving part for now), but I don't want to just copy paste some code I find online, I would like to learn enough VHDL to actually implement a UART. I understand that the UART will start reading incoming bits after the RX line has been pulled LOW (as this represents start of transmission). I want this event to start the clock for eight clock pulses so that the value of the TX line is read and stored in a 8-bit D_OUT register, but this has to stop after eight clock pulses as I don't want the D_OUT register to continuously store whatever value is on the TX-line even when the bus is idle. I was originally thinking of making an IF statement that registers that the TX-line has been pulled LOW and then sets some flag that says that transmission has started as well as starting the clock. After eight clock pulses this flag will be reset saying that transmission is done, the UART will then sit idle until the next time the TX-line is pulled LOW. The thing is that this IF-statement can't continuously reset the clock every time the TX-line is pulled LOW, it has to reset the clock once and then sit back, I'm not sure how to do this :(
 

You need to keep track of the number of bits with a counter. Use the counter value to decide if you're done or not. Once you reach the end count then you reset the counter and wait for the next time you see the RX line going low.
 

Several points are missing to a complete RX UART.
- start bit detection
- bit clock (baud rate) generator, using either oversampling or synchronization of bit clock to start bit
- RX-available signalling

You'll often find the transition between idle and receiving state coded as a state machine.
 
Last edited:

There has to be something basic that I don't understand about VHDL because I feel clueless about what actually compiles and what refuses to compile. Here's my code so far:

Code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;



ENTITY UART IS
	PORT (CLOCK_50 : IN STD_LOGIC;
			KEY : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
			--LEDR : OUT STD_LOGIC_VECTOR(9 DOWNTO 0);
			LED : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
			TX : OUT STD_LOGIC);
END UART;

architecture UART_beh of UART is

	 signal UARTREG : STD_LOGIC_VECTOR(8 DOWNTO 0);
	 signal RX : STD_LOGIC;
    signal prescaler: STD_LOGIC_VECTOR(24 downto 0) := "1101111101011110000100000"; -- 12,500,000 in binary
    signal prescaler_counter: STD_LOGIC_VECTOR(24 downto 0) := (others => '0');
    signal newClock : STD_LOGIC;
	 signal TRANSMISSION : STD_LOGIC;
	 signal bitnumber : UNSIGNED(4 downto 0) := (others => '0');
	 
begin



		LED <= UARTREG(8 DOWNTO 1);
	
		--RX <= KEY(0);

	
    process(CLOCK_50, RX)
    begin
			if rising_edge(CLOCK_50) then
				prescaler_counter <= prescaler_counter + 1;
				if(prescaler_counter > prescaler) then
				
					newClock <= not newClock;

					prescaler_counter <= (others => '0');
				end if;
			end if;
		  
		  
			if (RX = '0') then
				if (TRANSMISSION = '0') then
					prescaler_counter <= "0101111101011110000100000";
					newClock <= '0';
					TRANSMISSION <= '1';
				end if;
				

			end if;
			
			if rising_edge(newClock) then
				if (TRANSMISSION = '1') then
			   	UARTREG(to_integer(bitnumber)) <= RX;
					bitnumber <= bitnumber + 1;
				end if;
				
				if (bitnumber = 8) then
					bitnumber <= "00000";
					TRANSMISSION <= '0';
				end if;
			end if;
			
		end process;
	
	
		
end UART_beh;

This code compiles, but only if I remove "RX <= KEY(0);". If I include this line of code, the compiler gives me several errors including "Error (10818): Can't infer register for "TRANSMISSION" at UART.vhd(58) because it does not hold its value outside the clock edge". What's so different about KEY(0)?

Some other questions. I thought I understood the difference between SIGNED, UNSIGNED and STD_LOGIC, but replacing every STD_LOGIC with UNSIGNED(0 DOWNTO 0) didn't work at all, it just gave me a whole bunch of errors.

I'm also curious about what the difference between "hello <= '0' " and "hello <= 0 " or even "hello <= "0" ". I also don't understand why I sometimes see := used instead of <=
 
Last edited:

Where to start...?

You've got both std_logic_unsigned and numeric_std. Use numeric_std only then change all the std_logic_vector signals that you do "+ 1" to unsigned.
You've got a process with two clocks in it, bad
You've got combinational logic that is in the same process as your flip-flop logic setting signals like prescaler_counter asynchronous to CLOCK_50. I'm not sure what this will synthesize to.

You need to really read and understand a good book/tutorial on VHDL. You also need to learn how to translate between schematics of gates/flip-flops and VHDL. You should be working on basic flip-flops with resets and enables until you understand how they are translated to hardware (schematics), before writing a UART.

I'm having a hard time understanding how you could have programmed in C on a micro when you don't seem to understand the rudiments of types. (do you use char to define your counters? or string to define floats?)


Regards

- - - Updated - - -

There has to be something basic that I don't understand about VHDL because I feel clueless about what actually compiles and what refuses to compile.

I'm also curious about what the difference between "hello <= '0' " and "hello <= 0 " or even "hello <= "0" ". I also don't understand why I sometimes see := used instead of <=

Both of these are a result of not reading and understanding even the most basic tutorial of the language. Especially the part about the strong typing in VHDL.
 

Let's get the easy ones out of the way first. The simple overview:

hello <= '0';
This assigns the value of '0' or a logic low to a signal "hello" that was defined as a std_logic. The other option is '1' or logic high. Yes, there are other legal values as well, but they only pertain to synthesis, and I'm guessing you actually want to implement hardware.

hello <= 0;
This assigns the value of 0 (zero) to a signal defined as an INTEGER (as opposed to std_logic)

hello <= "0"
This assigns the CHARACTER "0" to a signal "hello" defined as a CHARACTER. Only useful in synthesis.

The := shows up most often in two places. The first is during signal declarations as a way of assigning a default value to the signal.
The second is how a value gets assigned to a VARIABLE, as opposed to a SIGNAL. Remember, in a process a signal is updated after the process suspends where a variable gets updated immediately. The general recommendation is avoid variables unless you really have a pressing need for them.

On to the code... As ads-ee pointed out, there are multiple clocked events in a single process. Like ads-ee, I have no idea what that's going to look like. I'm surprised it didn't flag that as well.
The reason you get the "does not hold its value outside the clock edge" error is in the center IF statement of the process you assign TRANSMISSION based on the state of RX... IF(RX = 0)... but you also try to assign it for a condition using the rising edge of newClock down below. One is edge sensitive, the other isn't. It can't do both.

This is NOT software - you are describing hardware. Software is the consecutive execution of statements; VHDL, Verilog, etc is all about concurrent actions. Try drawing the logic for what you want, then write to describe that. Get a good book, and when using VHDL, temporarily forget everything you know about software programming.
 

hello <= "0"
This assigns the STRING "0" to a signal "hello" defined as a CHARACTER. Only useful in synthesis.

Im going to have to correct you.
"0" is a string, and depending on the type of hello, affects what the string is.
So "0" could be a string.
"0" could be std_logic_vector
"0" could be unsigned or signed
"0" could be a bit_vector

But it is definately not a character, as that would be '0'
 

Thanks for the replies. I read the gmvhdl.com guide which shed some light at certain aspects, but I still don't understand how to make a UART. This is a uni exam, pity that we haven't had a single lecture about VHDL. I see most of us are trying to treat it as a programming language, raging about how they would rather use C than 'this shit'. I gave my UART another go (code below), but I just can't get there. I was thinking of making a state machine with something like 35 states, but that seems tedious (it might work though).

Code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;



ENTITY UART IS
	PORT(	CLOCK_50 : IN STD_LOGIC;
			KEY : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
			--LEDR : OUT STD_LOGIC_VECTOR(9 DOWNTO 0);
			LED : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
			TX : OUT STD_LOGIC);
END UART;

architecture UART_beh of UART is

	signal UARTREG : STD_LOGIC_VECTOR(8 DOWNTO 0);
	signal RX : STD_LOGIC;
	signal prescaler: STD_LOGIC_VECTOR(24 downto 0) := "1101111101011110000100000"; -- 12,500,000 in binary
	signal prescaler_counter: STD_LOGIC_VECTOR(24 downto 0) := (others => '0');
	signal newClock : STD_LOGIC;
	signal TRANSMISSION : STD_LOGIC;
	signal bitnumber : UNSIGNED(4 downto 0) := (others => '0');
	 
begin



	LED <= UARTREG(8 DOWNTO 1);
	
	RX <= KEY(0);

	
	process(CLOCK_50)
	begin
		if rising_edge(CLOCK_50) then
			if (TRANSMISSION = '1') then
				prescaler_counter <= prescaler_counter + 1;
				if(prescaler_counter > prescaler) then
					newClock <= not newClock;
					prescaler_counter <= (others => '0');
				end if;
			end if;
		end if;

	end process;
	
	
	process(RX)
	begin
		if falling_edge(RX) then
			TRANSMISSION <= '1';
		elsif (bitnumber = 10) then
			if (RX = '1') then
				TRANSMISSION <= '0';
			end if;
		end if;
	end process;
	
	process(newClock)
	begin
		if rising_edge(newClock) then
			UARTREG(to_integer(bitnumber)) <= RX;
			bitnumber <= bitnumber + 1;
		end if;
	end process;
			

	
		
end UART_beh;

It says that it can't infer register for TRANSMISSION because it changes value on both rising and falling edge of the clock. I'm not sure what it means to infer a register.

Look at this small process:

Code:
process(KEY(0))
	begin
		if (SW(3) = '1') then
			LED(0) <= SW(1);
		else 
			LED(0) <= SW(0);
		end if;
	end process;

Every time a change happens at KEY(0), the process is re-evaluated in a sequential fashion, right? My thinking was that LED(0) would show the value of SW(1) if SW(3) ='1' during start-up and that this would be the case even if SW(3) were to change in the future as long as KEY(0) doesn't trigger an event. In other words, LED(0)'s connection can't be changed unless KEY(0) triggers an event. I was clearly wrong though, if SW(3) changes value, so does LED(0)'s connection regardless of whether KEY(0) has triggered an event or not.
 
Last edited:

Thanks for the replies. I read the gmvhdl.com guide which shed some light at certain aspects,
I took a look at that and that isn't a very good tutorial.

I would look at https://www.asic-world.com/vhdl/index.html, which has lots of examples of coding synthesizable logic.

This is a uni exam, pity that we haven't had a single lecture about VHDL. I see most of us are trying to treat it as a programming language, raging about how they would rather use C than 'this shit'.
Hmmm, sounds like your uni isn't very good at the practical side of engineering. Heavy on the theory, with no practical usage of the theory (until you get to the exam). Seems like a lot of the students aren't adept at digital hardware design, and are more like software engineers.

I gave my UART another go (code below), but I just can't get there. I was thinking of making a state machine with something like 35 states, but that seems tedious (it might work though).
You probably should have a state machine but not some 35 state monster... Something along the lines of IDLE-START-DATA (loop 8 times here)-STOP-IDLE as the sequence it traverses.

Your code is still a mess.

1) Only use 1 clock in a process
2) Don't generate clocks from registers newClock, unless you understand everything that can go wrong with using them and know how to circumvent the problems (basicaly don't use them).
3) RX shouldn't be used as a clock, as a novice you never want to use input data as a clock.
4) You need to have a baud rate generator. (I suppose that's what your prescaler is for)
5) You should probably look at the UART design on opencores for inspiration and to get an idea of the blocks you'll need. As poorly documented and poorly coded as most of the designs are on opencores, at least many of the basic designs like the UART have been tested in HW.

It says that it can't infer register for TRANSMISSION because it changes value on both rising and falling edge of the clock. I'm not sure what it means to infer a register.
Changes on falling edge of RX (which shouldn't be used as a clock)
Code:
if falling_edge(RX) then
Now you're looking at the high level of RX when bitnumber is 10, which sort of makes this is a gated rising edge clock.
Code:
elsif (bitnumber = 10) then
  if (RX = '1') then

The basic DFF with enable and asynchronous reset is written like this:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
process (clk, rst) begin
  if rst = '1' then
    q <= '0';
  elsif rising_edge (clk) then
    -- the stuff in here can have multiple nested if statements and/or case statements
    if en = '1' then
      q <= d;
    end if;
    --
  end if;
end process;



Regards
 

I'll take a look at that guide, thanks :) One quick question, why do you mean by using "as clock"? Does that mean to have a signal in the sensitivity list or do you mean using "rising_edge" and/or "falling_edge"?

Code:
process(KEY(1))
	begin
		if rising_edge(KEY(0)) then
			if (SW(3) = '1') then
				LED(0) <= '1';
			else
				LED(0) <= '0';
			end if;
		
			if SW(2) = '1' then
				LED(1) <= '1';
			else 
				LED(1) <= '0';
			end if;
		end if;
	end process;

LED(1) changes value regardless of whether KEY(1) changes value, how is that possible? I thought nothing in that process could change unless something happens in the sensitivity list?
 

rising_edge and falling_edge means the signal is being used as a clock.

You do know about DFFs, don't you? Did you take any digital design classes? If that wasn't a requirement for a class that uses VHDL then that University has problems with it's curriculum.
Capture.PNG

LED(1) changes value regardless of whether KEY(1) changes value, how is that possible? I thought nothing in that process could change unless something happens in the sensitivity list?
Because KEY(1) is in the sensitivity list and KEY(0) is in the rising_edge statement.

And if you are actually using some external "key" (i.e. a switch) then you absolutely don't want to do this ever. Switches are not clean make or break devices, unless they are non-mechanical switches like some sort of FET switch. You'll see many rising and falling edge transitions off a switch, which must be debounced before it can be used.

Regards

- - - Updated - - -

I don't want to discourage you, but you seem to be missing two of the primary skills to complete this project.

1) Knowing VHDL, (i.e. having read a book on VHDL so you know the syntax, understand types, and know the synthesis templates for various digital logic structures)
2) Digital design

If I'm wrong about number 2 forgive me, but you haven't shown that you understand how to design a digital circuit.
 

We had a digital design class last year, taught us gates, flip-flops, karnaugh map, registers, half/full adders and all that. Our lecturer spent like 15 mins telling us how FPGA's work, how these logic elements can be rearranged and connected to make different digital circuits. Is VHDL really so vast that I need to read an entire book to understand it? In that case my bachelor has to be postponed by a year. I assumed that VHDL was easy enough to just learn by reading a little bit online combined with trial and error, seems like this uni is making a massive mistake not teaching it to us in class if it's that's hard to comprehend.

Because KEY(1) is in the sensitivity list and KEY(0) is in the rising_edge statement.

I found this online:

The signal sensitivity list is used to specify which signals should cause the process to be re-evaluated. Whenever any event occurs on one of the signals in the sensitivity list, the process is re-evaluated. A process is evaluated by performing each statement that it contains.

In order for the statements inside the process to be performed, one of the signals in the sensitivity list has to change value? So how can my LED(1) change value when KEY(1)'s value is unchanged? What difference does the sensitivity list make in this particular example?

I'm using a DE2-nano board, I assume that one of those SMD caps are used for debouncing (seems that way at least).
 

Realistically VHDL is not that hard to learn (I just read the Perry book cover to cover), but you have to start by reading a book and not just trying to pick up what you need (like you can with some software languages and most scripting languages). Trouble is right now you don't know what you need to know before you try picking up the next topic. At least a proper tutorial and or a book will present the material in a sensible order that builds on what you learn.

Then the simulator isn't truely VHDL compliant as only the items in the sensitivity list should cause the process to be evaluated. This is why if you don't include all the signals in the sensitivity list that cause events to occur in the process you get simulation synthesis mismatches. Maybe this simulator tries to act more like a synthesis tool and ignores the sensitivity list. Is there any warnings about incomplete sensitivity lists?

A cap isn't going to debounce a physical switch, unless the RC time constant is on the order of 10's of ms or more, and then your signal rise time is trash so optimally you would want to send it to the FPGA through a schmitt trigger buffer to clean up the edges. After that you would use a synchronizer if it's going to a clock domain in the FPGA. Personally I just add a synchronizer followed by a debouce circuit in the FPGA, which allows me to set a parameter in the code to modify the duration of the required level change before it switches state.

Regards
 

I assumed that VHDL was easy enough to just learn by reading a little bit online combined with trial and error.
I think that's basically possible, if you have some experience with digital logic.

To apply trial and error with some success, your digital design should have a reasonable purpose and specification. And the VHDL coding should start from a profound template. Did you review the VHDL templates offered by the Quartus editor?
 

I made it another go. It compiles, but complains about some signals not being in the sensitivity list. If I don't need the process to be re-evaluated, there is no real need to put every signal that is read inside the sensitivity list, right? I tried uploading it to my DE-2-nano, but it doesn't work. LED(1 DOWNTO 0) are supposed to show me which state it's in, but both leds seem to glow quite dimly so I guess it's switching states with the same frequency as CLOCK_50 (which I don't understand).

Code:
architecture UART_beh of UART is

	signal UARTREG : STD_LOGIC_VECTOR(8 DOWNTO 0);
	signal RX : STD_LOGIC;
	signal prescaler: STD_LOGIC_VECTOR(24 downto 0) := "1101111101011110000100000"; -- 12,500,000 in binary
	signal prescaler_counter: STD_LOGIC_VECTOR(24 downto 0) := (others => '0');
	signal newClock : STD_LOGIC;
	signal bitnumber : UNSIGNED(4 downto 0) := (others => '0');
	
	type statetype is (idle, start, transfer, stop); 
	signal state,nextstate: statetype; 
	 
begin

	--LED <= UARTREG(8 DOWNTO 1);
	RX <= KEY(0);
	--LED(0) <= newClock;
	

	process(CLOCK_50)
	begin
		if rising_edge(CLOCK_50) then
			state <= nextstate;
			prescaler_counter <= prescaler_counter + 1;
			if(prescaler_counter > prescaler) then
				newClock <= not newClock;
				prescaler_counter <= (others => '0');
			elsif (state = idle) then
				newClock <= '0';
				prescaler_counter <= (others => '0');
			end if;
		end if;
	end process;
	
	
	process(state, RX, newClock)
	begin
		case state is
		
			when idle => 
				if (RX = '0') then
					nextstate <= start;
				end if;
				led(1 DOWNTO 0) <= "00";
				
			when start =>
				if (newClock='1' and newClock'last_value='0') then
					nextstate <= transfer;
				end if;
				led(1 DOWNTO 0) <= "01";
			
			when transfer =>
				if (bitnumber = 8) then
					nextstate <= stop;
				elsif (newClock='1' and newClock'last_value='0') then
					UARTREG(to_integer(bitnumber)) <= RX;
					bitnumber <= bitnumber + 1;
				end if;
				led(1 DOWNTO 0) <= "10";
			
			when stop =>
				bitnumber <= "00000";
				if (RX = '1') then
					nextstate <= idle;
				end if;
				led(1 DOWNTO 0) <= "11";
				
			when others => nextstate <= idle;
		end case;
	end process;
					


end UART_beh;

I don't get what the deal about clocks are. I've now limited myself to only using CLOCK_50 as a clock, but then the compiler complains and says "Warning (332060): Node: newClock was determined to be a clock but was found without an associated clock assignment.". What is really the difference between using rising_edge and having a signal in the sensitivity list? When a rising or falling edge of a signal represents some kind of change, it's called a clock, right? If a signal is present in the sensitivity list it means that something will happen when that signal changes value (rising or falling edge) so I don't understand the difference.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top