VHDL: How can I truncate a hex constant to match a smaller vector?  - Page 1
Forum section: electronics / general

author: Dongulus
author_rank: Regular Contributor
timestamp: March 17, 2014, 04:41:09 pm
content: I'm having some trouble assigning constant hex values to vectors of a smaller size. In my current project, I am using a FPGA to receive 7-bit ASCII characters from a terminal emulator application on a PC. I need to compare and assign 7-bit logic vectors with hard coded values that are most easily read as two digit hex, e.g. 0x0D.In VHDL, I want to make this sort of assignment or compare:Code:signal AsciiChar : std_logic_vector(6 downto 0) := x"0D";....if (AsciiChar = x"0D") then ...But assigning or comparing an 8-bit value with a 7-bit vector gives me mis-match errors.For anyone familiar with Verilog, this operation is trivial,Code:CR = 7'h0D;but VHDL doesn't seem to easily offer the same sort of function for the case of assigning a truncated hex value. Does anyone know of some easy way to do this?By the way, I found the function named "align_size" in the "std_logic_arith" package that seems like should work, but Quartus keeps giving me an error that the function isn't defined, even though I have the std_logic_arith package declared.

author: mrflibble
author_rank: Super Contributor
timestamp: March 17, 2014, 04:53:45 pm
content: How about specifying the length of that hex literal, like so:Code:signal AsciiChar : std_logic_vector(6 downto 0) := x"0D";....if (AsciiChar = 7x"0D") then ...Edit:Looks like this feature was added in VHDL-2008. Also check this one:http://www.doulos.com/knowhow/vhdl_designers_guide/vhdl_2008/vhdl_200x_ease/#bistring

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: March 17, 2014, 05:03:53 pm
content: You could just make the signal 8 bits wide and tie the top bit low - it will get optimised out.

author: mrflibble
author_rank: Super Contributor
timestamp: March 17, 2014, 05:37:29 pm
content: Quote from: mikeselectricstuff on March 17, 2014, 05:03:53 pmYou could, but that's rather nasty and will mess up your modules real quick. Especially if this 7-bit signal comes from another module. If you want to go that route the sortof doable way is to keep the signal 7-bits, then extend to 8-bits right at the comparison operator. As in concatenate with a 0 MSB, and compare that to the 8-bit literal. At least that way you can see wtf is going on. Or maybe you meant this...But with a bit of luck Dongulus' tools support VHDL-2008, then it's problem solved in the exact same way as it is for verilog.

author: FrankBuss
author_rank: Unknown
timestamp: March 17, 2014, 06:52:52 pm
content: Use hex integer literals and to_unsigned to convert it to a vector of the required length, then std_logic_vector to convert it, if you don't use unsigned:Code:if AsciiChar = std_logic_vector(to_unsigned(16#0D#, 7)) thenTo make it more readable, you could create a subtype and a function:Code:foo: process(AsciiChar) issubtype AsciiType is std_logic_vector(6 downto 0);function b7(v: integer) return AsciiType isbeginreturn AsciiType(to_unsigned(v, AsciiType'Length));end function;beginif AsciiChar = b7(16#0D#) then...end if;end process;

author: mrflibble
author_rank: Super Contributor
timestamp: March 17, 2014, 07:19:21 pm
content: Quote from: Dongulus on March 17, 2014, 04:41:09 pmQuote from:http://quartushelp.altera.com/12.1/mergedProjects/hdl/vhdl/vhdl_list_2008_vhdl_support.htmQuote from: mrflibble on March 17, 2014, 04:53:45 pmProblem solved?note the 7

author: Dongulus
author_rank: Regular Contributor
timestamp: March 17, 2014, 08:01:04 pm
content: Quote from: FrankBuss on March 17, 2014, 06:52:52 pmYou are right FrankBuss, for this case a subtype will be useful. Luckily, looking further I found that the work has been already done for me because the standard VHDL package already includes an enumerated "character" type. In fact, now I won't even need to assign or compare signals with hex values because I can use character literals instead (now I don't need to look up ASCII tables either).Still, for future reference I want to find a good solution for the general case.Quote from: FrankBuss on March 17, 2014, 06:52:52 pmYes, I got the above statement to work. It's definitely not pretty, but at least I know I have a working solution. As you have stated I could always write a function to make it more readable if the design warrants it.Quote from: mrflibble on March 17, 2014, 05:37:29 pmI'm really hesitant to adopt the 2008 standard. I would maybe consider it for a personal project, but this design isn't and I'm most likely required to use the 1993 standard.Quote from: mikeselectricstuff on March 17, 2014, 05:03:53 pmYeah, good idea. I had decided to do this before I found out that the character type existed. Not something I would want to do in most other cases of awkward vector lengths though.

author: mrflibble
author_rank: Super Contributor
timestamp: March 17, 2014, 08:28:34 pm
content: Quote from: Dongulus on March 17, 2014, 08:01:04 pmFair point. In that case FrankBuss' solution using a function to cast and then compare looks to be the cleanest option for the general case.

author: marshallh
author_rank: Unknown
timestamp: March 17, 2014, 08:32:51 pm
content: Use verilog and abuse bit widths with impunity and at your own risk

author: mrflibble
author_rank: Super Contributor
timestamp: March 17, 2014, 09:24:00 pm
content: Quote from: marshallh on March 17, 2014, 08:32:51 pmOr my personal favorite, make a hard to spot typo in one of your signal names. And then the tools will happily assume that of course you meant that, and will whip up a new set of wires for you. Which will then result in all sorts of fun!Fell for that one a few times. I've been using`default nettype noneever since, to prevent that particular headache.

author: miguelvp
author_rank: Super Contributor
timestamp: March 18, 2014, 02:34:32 am
content: Only thing that comes to mind other than VHDL 2008 is to mix binary with hex by using the & concatenation.Code:signal AsciiChar : std_logic_vector(6 downto 0) := "000" & x"D";....if (AsciiChar = ("000" & x"D")) then ...Or use binary only, less pretty and more confusingCode:signal AsciiChar : std_logic_vector(6 downto 0) := "0001101";....if (AsciiChar = "0001101") then ...Or better yet, since you need 7 bits, concatenate octal and hexCode:signal AsciiChar : std_logic_vector(6 downto 0) := o"0" & x"D";....if (AsciiChar = (o"0" & x"D")) then ...