VHDL testbench report error - indexing

working on a project with a self checking test bench and having a problem I do not understand.
The problem for the following code is an error in the simulation. I will point to where the error is coming from in the code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
ENTITY TestBenchAutomated IS
-- Generics passed in
generic (m: integer := 3; n: integer := 5; h: integer := 4; DATA_SIZE: integer :=5);
END TestBenchAutomated;
ARCHITECTURE behavior OF TestBenchAutomated IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT TopLevelM_M
generic (m: integer := 3; n: integer := 5; h: integer := 4; DATA_SIZE: integer :=5);
PORT(
clk : IN std_logic;
next_in : IN std_logic; --User input
rst_in : IN std_logic; --User input
OUTPUT : OUT SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0) --Calculated DATA output
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal next_in : std_logic := '0';
signal rst_in : std_logic := '0';
--Outputs
signal OUTPUT : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
--Variable to be used in assert section
type Vector is record
OUTPUT_test : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
end record;
type VectorArray is array (natural range <>) of Vector;
constant Vectors : VectorArray := (
-- Values to be compaired to calculated output
(OUTPUT_test =>"000000110000"), -- 48
(OUTPUT_test =>"000011110110"), -- 246
(OUTPUT_test =>"000101001000"), -- 382 <--- Purposefully incorrect value, Should be '000100001000' = 264
(OUTPUT_test =>"111111010011"), -- -45
(OUTPUT_test =>"111101001100"), -- -180
(OUTPUT_test =>"111111001111"), -- -49
(OUTPUT_test =>"000000101011"), -- 43 Purposefully incorrect value, Should be '000010101011' = 171
(OUTPUT_test =>"000000010011"), -- 19
(OUTPUT_test =>"111111100101"), -- -27
(OUTPUT_test =>"111110111011"), -- -69
(OUTPUT_test =>"111110111011"), -- -69
(OUTPUT_test =>"000000101101"), -- 45
(OUTPUT_test =>"111011011110"), -- -290
(OUTPUT_test =>"000001010110"), -- 86
(OUTPUT_test =>"000011110010"), -- 242
(OUTPUT_test =>"00000111110"), -- 125
(OUTPUT_test =>"111111001001"), -- -55
(OUTPUT_test =>"000100010101"), -- 277
(OUTPUT_test =>"111111100011"), -- -29
(OUTPUT_test =>"111101111101"));-- -131
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: TopLevelM_M PORT MAP (
clk => clk,
next_in => next_in,
rst_in => rst_in,
OUTPUT => OUTPUT
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Process to simulate user input and to check output is correct
Test :process
variable i : integer;
begin
wait for 100 ns;
rst_in <= '1';
wait for clk_period*3;
rst_in <= '0';
--Loops through enough times to cover matrix and more to show it freezes in S_Wait state
for i in 0 to 50 loop
for i in Vectors'range loop
next_in <= '1';
wait for clk_period*5;
next_in <= '0';
wait for clk_period*4; --Appropriate amount of clock cycles needed for calculations to be displayed at output
--Check the output is the same as expected
assert OUTPUT = Vectors(i).OUTPUT_test
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test))) --& lf &
--"But got" & integer'image(i)(to_integer(signed(OUTPUT)))
severity error;
end loop;
end loop;
wait;
end process;
END;
As you can see in the vector, I have inserted two incorrect values to make sure the code works. I there for expect an error in the simulation telling me that there is an error on address 2 of the vector and what integer it is. However, the simulation stops and i get this:
ERROR: Index 328 out of bound 1 to 1.
ERROR: In process TestBenchAutomated.vhd:Test
INFO: Simulator is stopped.
Obviously the integer 328 that is represented by the binary number in the vector causes this error, but I dont understand why it causes THIS error instead of the one I have coded. What is this index out of bound OF?
Any help would be much appreciated.
Thanks

This:
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
Should be:
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(to_integer((Vectors(i).OUTPUT_test)))
It's complaining that the value (to_integer((Vectors(i).OUTPUT_test))) is out of range for a character when it should have been used as parameter to 'IMAGE, which you supplied already as i.
For a simplified test case:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
constant m: integer := 3;
constant n: integer := 5;
constant h: integer := 4;
constant DATA_SIZE: integer :=5;
end entity;
architecture fum of foo is
signal OUTPUT : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0) := "000011110110" ;
type Vector is record
OUTPUT_test : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
end record;
type VectorArray is array (natural range <>) of Vector;
constant Vectors : VectorArray := (
-- Values to be compaired to calculated output
(OUTPUT_test =>"000011110110"), -- 246 (CORRECT)
(OUTPUT_test =>"000101001000") -- 382 (INCORRECT)
);
begin
TEST:
process
begin
for i in Vectors'RANGE loop
assert OUTPUT = Vectors(i).OUTPUT_test
report "Incorrect Output on vector line " & integer'image(i) &
-- lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
lf & "Expected:" & integer'image(to_integer((Vectors(i).OUTPUT_test)))
severity error;
end loop;
wait;
end process;
end architecture;
And the incorrect usage, Nick Gasson's nvc gave:
david_koontz#Macbook: nvc -a foo.vhdl
** Error: expected 2 parameters for attribute IMAGE but have 3
File foo.vhdl, Line 34
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_t ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
With the correct number of arguments to `'IMAGE' (shown in the example):
david_koontz#Macbook: nvc -r foo
** Fatal: 0ms+0: Assertion Error: Incorrect Output on vector line 1
Expected:328
Process :foo:test
File foo.vhdl, Line 32
Found a ghdl bug not reporting this when it likely should. It worked either way (this should be a run time error). An integer value of 382 isn't a character eligible for concatenation.
Addendum:
Tristan Gingold (ghdl author) pointed out that the expression is an element index to the string output of the 'IMAGE function.
Further analysis reveals the basis for the error message on the original code for the question:
& integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
T'IMAGE(X)
Kind: Function.
Prefix: Any scalar type or subtype T.
Parameter: An expression whose type is the base type of T.
Result Type: Type String.
Result: The string representation of the parameter value, without
leading or trailing whitespace.
No concatenation operator following.
(to_integer( ( Vectors(i).OUTPUT ) ) ) returns the integer value for the record element OUTPUT, type signed. (superfluous parentheses aside).
The contents of Vectors(i).OUTPUT is
constant Vectors : VectorArray := (
(OUTPUT_test =>"000011110110"), -- 246 (CORRECT)
(OUTPUT_test =>"000101001000") -- 382 (INCORRECT)
);
The 382 should be 328, its 0x148. Dyslexia is hard to spell.
And in this case for i = 1 (Vectors'RANGE is (0 to 1), is
"000101001000" which to_integer is 328, out of range for an element of a string (element type character).
An integer, value 328 or not is not an element index type for a record (while OUTPUT is).
The subtype for the unnamed string output of 'IMAGE is the length of the string for i, whose value is 1, the length is 1, the range is 1 to 1. 328 is out of range.
Notice the ISIM message said exactly that in the original model:
ERROR: Index 328 out of bound 1 to 1. ERROR: In process TestBenchAutomated.vhd:Test
This still looks like a ghdl error. It does also make nvc's error message suspect however.

Related

Iteration limit reached - simple counter in VHDL FSM

I'm having "Iteration limit reached" error in a simple FSM.
This is a part of of a bigger FSM I have to do for a class assignment, and I tracked the problem to this specific part.
The FSM will be controlling a counter, the state IDLE waits for inputs, ZERO sets the counter to zero, and the INCREMENT state increments the counter by one.
When simulating, the error occurs at the first time the input "inc" is high and the clock rises.
If I change the statement "temp := temp + 1;" for "temp := anything" the error stops. I really don't know what can be wrong, as for what I have found this error occurs when changing signals in the process sensitivity list inside the process itself.
I'm using Quartus II for the simulation.
Sorry for english mistakes.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.all;
entity fsm is
port
(
clock: in std_logic;
reset: in std_logic;
inc: in std_logic;
count: out std_logic_vector (13 downto 0);
cur_state: out std_logic_vector (1 downto 0)
);
end fsm;
architecture behaviour of fsm is
type state_type is (IDLE, INCREMENT, ZERO);
signal PS, NS: state_type;
begin
sync_proc: process (clock, reset)
begin
if (reset = '1') then
PS <= ZERO;
elsif (rising_edge(clock)) then
PS <= NS;
end if;
end process sync_proc;
comb_proc: process (PS, inc)
variable temp: unsigned (13 downto 0);
begin
case PS is
when IDLE =>
if (inc = '1') then
NS <= INCREMENT;
else
NS <= IDLE;
end if;
when INCREMENT =>
temp := temp + 1;
NS <= IDLE;
when ZERO =>
temp := "00000000000000";
NS <= IDLE;
when others =>
NS <= IDLE;
end case;
count <= std_logic_vector(temp);
end process comb_proc;
with PS select
cur_state <= "00" when IDLE,
"01" when INCREMENT,
"10" when ZERO,
"11" when others;
end behaviour;
You have a very serious CONCEPTUAL mistake in your case statement. Because it produces a combinational circuit (the combinational part of your FSM), it does not have memory, so it can't implement the equation "temp := temp + 1" (because, having no memory, it doesn't know what the value of temp is).
You can see more about this in chapter 11 of "Finite State Machines in Hardware...", by V.Pedroni, published by MIT.

Read file line of unknown size as string in VHDL

I'm trying to make a Test Bench where a file of one single line, where posible characters are "1" and "0". I've to read them all, and use one by one as input in my DUT.
So, in my TB, I've defined a process like the following, in order to read the file an pass it values to my DUT.
stim_proc: process
file input_file: TEXT is in "DatosEntrada.dat";
variable rdline : LINE;
variable line_content : string ( 1 to 4);
variable readed_char : character;
variable j : integer := 0;
begin
while not endfile(input_file) loop
readline(input_file, rdline);
--read(rdline, line_content);
for j in 1 to rdline'length-1 loop
readed_char := line_content(j);
if (readed_char = '1') then
input <= '1';
else
input <= '0';
end if;
wait for clk_period;
end loop;
end loop;
end process;
I'm reading the first (and only) line of my file with the first readline execution. After this, this loop shouldn't execute again.
Then, data from file should be inside rdline. So I've to process it. In order to do it, I've tried to loop over rdline length, but this loop doesn't execute.
for j in 1 to rdline'length-1 loop
So I thought I need to read this line in order to loop over it, and tried to move its data to a string var. The problem is that vector var like string need to have a defined size, and I don't know the file line size.
I've tried reading each time 4 chars from rdline into a string, process it, then repeat. However, I couldn't make it work.
I've found quite lot examples about reading files which have defined line formats, like columns or expected integers.
But how can I read an unknown text of one line?
This readed_char := line_content(j); doesn't work when line_content isn't loaded. Otherwise your attempt to read values is basically sound.
The end of line is not contained in a read LINE buffer, there's no reason to not read the last character of rdline. An end of line is signaled by one or more format effectors other than horizontal tab, and just the line contents are present.
There's also this inference that you have some relationship to a clock edge and not just a clock period. The following example shows that. Note you can also supply an offset from an edge using a wait for time_value.
A loop constant is declared in the loop statement. The variable j you declared is not the same j the loop uses. The loop statement hides the j in the outer declarative region (the variable declaration in the process statement).
Your code treats any other character in the string buffer than '1' as a '0'. I didn't change that, do demonstrate it. You should be aware of the impact.
A LINE is an allocated string of some length dependent on the length of a line in your read file. Every time you call readline the string rdline points to is updated. It doesn't leak memory, the previous buffer rdline pointed to released. You can read the length by using the 'RIGHT attribute or as in this case simply consume all the characters.
There may be line length limits in a VHDL tool implementation. There are none defined in the standard other than the maximum length of a string (POSITIVE'RIGHT).
An MCVE:
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
entity foo is
end entity;
architecture fum of foo is
signal input: std_logic ;
signal clk: std_logic := '0';
constant clk_period: time := 10 ns;
begin
stim_proc:
process
file input_file: TEXT is in "DatosEntrada.dat";
variable rdline: LINE;
-- variable line_content : string ( 1 to 4);
-- variable readed_char : character;
-- variable j: integer := 0;
begin
while not endfile(input_file) loop
readline(input_file, rdline);
--read(rdline, line_content);
-- for j in 1 to rdline'length - 1 loop -- EOL not in rdline
for j in rdline'range loop
-- readed_char := line_content(j);
-- if readed_char = '1' then
if rdline(j) = '1' then -- changed
input <= '1';
else
input <= '0';
end if;
-- wait for clk_period; -- sync to edge instead
wait until falling_edge(clk); -- input related to clk edge
end loop;
end loop;
wait; -- added prevents needless loops
end process;
CLOCK:
process
begin
wait for clk_period/2;
clk <= not clk;
if now > 32 * clk_period then
wait;
end if;
end process;
end architecture;
And for DatosEntrada.dat containing:
11011110001HELLO11230000
That produces:
Where you can see all non '1' characters are interpreted as '0'.

Baud Rate Clock VHDL -- floating point exception error and/or style issues

I am trying to build a generic baud rate generator process for a uart transmitter.
The transmitter works fine if I ignore the baud rate divider and pass in the clk signal in the sensitivity list. But I get errors (describe in code comments) if I try to implement the divider. I tried two different methods and both either gave an error, or did not have the expected output. Yes, the exact code posted will not work since I assign fbaud twice, I comment one out to test.
Perhaps I don't understand how the baud generator is supposed to work. From my understanding, the fpga clock runs at 50mHz which is to fast for the rs232 communication. So we need to wait a certain number of clock cycles before we can transmit our character.
In this case, we have a variable baud so we divide the stock clock by the baud generator to get the number of clock cycles we need to wait before sending our 'tick' signal to the transmit state machine.
The baud divider is set in the test bench to x"000008".
-- Universal Asynch Receiver Transmitter
---------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity eds_uart is
generic (width : positive := 16);
port ( clk,reset: in std_logic ;
din_wen: in std_logic; -- state machine sets value thus buffer needed
brd : in std_logic_vector(23 downto 0); -- buad rate dividor
din : in std_logic_vector(7 downto 0); -- input value
txd: out std_logic; -- sent data bit
tx_busy : buffer std_logic -- sent data bit active
);
end entity eds_uart;
architecture behaviour of eds_uart is
type state_type is (idle_s, wait_s, transmit_s); -- three possible states of uat
signal current_s: state_type;
signal tick: std_logic := '0'; -- baud rate clock
signal count: integer := 0; -- count number of characters sent
signal shift: std_logic_vector(9 downto 0); -- intermediate vector to be shifted
signal fbaud: integer := 0;
signal fbaud_counter: integer := 0;
begin
--- process that is causing the issue.
process(clk, brd) begin
fbaud <= (50000000)/to_integer(signed(brd)); -- 50,000,000 is the default clock Hz
------ error message ------
--# ** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
-- # Time: 0 ns Iteration: 0 Instance: /eds_uart_tb/inst_uart
-- # ** Fatal: (SIGFPE) Floating point exception.
--# Time: 0 ns Iteration: 0 Process: /eds_uart_tb/inst_uart/line__29 File:
fbaud <= 50000;
--- error ---
-- this command simply does not work, it compiles and runs though
-- I don't get any transitions in my output wave
-- I don't think it is entering the transmit stage based on a clock signal
if (rising_edge(clk)) then
if (fbaud_counter = fbaud) then -- tick when proper number of counts have appeared
tick <= '1';
elsif (fbaud_counter < fbaud) then
tick <= '0';
fbaud_counter <= fbaud_counter + 1;
end if;
end if;
end process;
process(tick, reset, din) begin
if (reset = '1') then
current_s <= idle_s; -- default state
count <= 0; -- reset character counter
txd <= '1';
tx_busy <= '0';
elsif (current_s = idle_s and din_wen = '1') then -- transition when write enable is high
current_s <= wait_s; -- transition
tx_busy <= '1';
shift <= '1' & din & '0'; -- init shift value
end if;
if(rising_edge(tick)) then
if (current_s = wait_s) then -- transition on clock signal
current_s <= transmit_s;
elsif (current_s = transmit_s) then -- transition on clock signal
if (count < 9) then
txd <= shift(0); -- output value
shift <= '0' & shift(9 downto 1); -- shift to next value
count <= count + 1; -- increment counter
current_s <= transmit_s; -- dont change state
elsif (count = 9) then
txd <= shift(0); -- send last element
count <= 0;
tx_busy <= '0'; -- reset busy signal
current_s <= idle_s; -- start process again
end if;
end if;
end if;
end process;
end architecture behaviour ;
There are a few potential problems with this code, but what seems to be causing your failure is that you're declaring fbaud_counter as an integer but with no range limit specified, and more critically, you're not clearing it when it reached your fbaud count value. Since you never reset the value after the count is reached, it will continue counting through all 2^32 values before it wraps around and matches fbaud again. A range limit is probably a good idea anyway, but either way, if you don't reset it, your baud rate will not be correct. For instance:
if (rising_edge(clk)) then
if (fbaud_counter = fbaud - 1) then
tick <= '1';
fbaud_counter <= 0;
else
tick <= '0';
fbaud_counter <= fbaud_counter + 1;
end if;
end if;
Note that there's really no need for an elsif condition there, as there really isn't a condition where you don't otherwise want to set tick to '0' or increment your count. Note that I'm also counting to fbaud - 1 - If you start at 0, counting all the way to fbaud may put your rate off very slightly.
edit
I simulated the above with the changes I recommended to the process, and I got a response on txd (as well as a steady tick). Are you sure you're simulating long enough? Assuming your clock is set up to be 50 MHz as your code indicates it should be, setting brd to x"000008" will give you an incredibly slow tick rate (8 Hz, oddly enough). I reduced the numerator to 5000 just to speed things up a bit.
I also realize I didn't cover your floating point exception (thanks for pointing that out).
The warning is a hint as to the error. "metavalue detected, returning 0". The warning indicates to_integer is trying to convert a value that it can't resolve to a 1 or 0 (e.g. 'X', or another such std_logic value), and of course you can't divide by 0. This is most likely an initialization problem (note that your fatal error says Time: 0 ns Iteration: 0). In your testbench, how is brd driven initially? Can you give it a default value? If not, you will need to guard against this condition some other way.
When you simulate it it sounds like your brd input is not initialized, so the Us are turning into 0s and you are dividing by zero - hence the exception.
Also, this will synthesise to something very big, resource-wise:
fbaud <= (50000000)/to_integer(signed(brd));
You are asking for this to be calculated every clock cycle, which is a big ask from the hardware.
The usual method is to accept a terminal count (your fbaud) as the input and let the controlling software figure out what the value should be. Or calculate it at compile time as a constant, depending on how flexible you need to be.

VHDL shift operators?

I'm still trying to get used to some of the quirks of VHDL and I'm having a bit of an issue. First off, I understand that shift operators like rol, ror, ssl, srl, etc. are not synthesizeable. The purpose of this lab is to use a golden model to check against a synthesizeable version of the same thing in a testbench.
Now, the purpose of this program is to convert thermometer code into a 3-bit binary number. So, in other words, thermometer code "00000001" = "001", "00000011" = "010", "00000111" = "011", etc. I'm basically trying to count the number of 1's in the string from right to left. There will be no case where a '0' is placed between the string of 1's, so the vector "00011101" is invalid and will never occur.
I've devised a non-synthesizeable (and so far, non-compile-able) algorithm that I can't figure out how to get working. Basically, the idea is to read the thermometer code, shift it right and increment a counter until the thermometer code equals zero, and then assign the counter value to the 3-bit std_logic_vector. Below is the code I've done so-far.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity therm2bin_g is
port(therm : inout std_logic_vector(6 downto 0); -- thermometer code
bin : out std_logic_vector(2 downto 0); -- binary code
i : integer range 0 to 7);
end therm2bin_g;
architecture behavioral_g of therm2bin_g is
begin
golden : process(therm)
begin
while(therm /= "00000000") loop
therm <= therm srl 1;
i = i + 1;
end loop;
bin <= std_logic'(to_unsigned(i,3));
end process golden;
behavioral_g;
here's a version that is synthesisable. the while loop is replaced by a for loop. srl is implemented explicitly:
entity therm2bin_g is
port(therm : inout std_logic_vector(6 downto 0); -- thermometer code
bin : out std_logic_vector(2 downto 0); -- binary code
i : out integer range 0 to 7);
end therm2bin_g;
architecture behavioral_g of therm2bin_g is
begin
golden : process(therm)
variable i_internal: integer range 0 to 7;
begin
i_internal:=0;
for idx in 0 to therm'length loop
if therm/="0000000" then
therm<='0' & therm(therm'left downto 1);
i_internal := i_internal + 1;
end if;
end loop;
bin<=std_logic_vector(to_unsigned(i_internal,bin'length));
i<=i_internal;
end process golden;
end behavioral_g;
"... operators like rol, ror, ssl, srl, etc. are not synthesizeable..."
Who says that on who's authority? Have you checked? On which synthesis tool? Was it a recent version, or a version from the early 1990s?
Note that the argument that some tools might not support it is just silly. The fact that some kitchens might not have an oven does not stop people from writing recipes for cake.

VHDL std_logic_vector indexing with "downto"

I would like to set bits of a std_logic_vector separately in order to easily set comments for individual bits or group of bits. Here is what I have:
signal DataOut : std_logic_vector(7 downto 0);
...
DataOut <= ( 5=>'1', -- Instruction defined
4=>'1', -- Data length control bit, high=8bit bus mode selected
3=>'1', -- Display Line Number ctrl bit, high & N3 option pin to VDD=3 lines display
2=>'0', -- Double height font type control byte, not selected
1 downto 0=>"01", -- Select Instruction table1
others=>'0' -- for bits 6,7
);
However, I've a problem with the "downto" statement, I get the following error using Xilinx ISE:
Type std_ulogic does not match with a string litteral
Any solution to avoid using the equivalent
1=>'0',
0=>'1',
and to allow me to set bits by block?
The assignment X downto Y => 'A' is correct when A is a element of array. For example, this snippet is correct:
1 downto 0 => '1',
And this snippet is wrong:
1 downto 0 => "01",
Therefore, your assignment is illegal. As your code, you can assign as:
DataOut <= ( 5 downto 3 =>'1',
2 downto 1 =>'0',
0 => '1',
others=>'0'
);
If you want to access/assign by a feild of array, you can use concatenation:
DataOut <= Something_0 & Something_1 & "01";
While Something_* is std_logic_vector
Another answer is concatenation using '&', which loses the clarity of named association, though you can recover some of the self-documentation with named constants
constant Instr_Defined : std_ulogic := '1';
constant Bus_8_Bit : std_ulogic := '1';
DataOut <= "00" & Instr_Defined
& Bus_8_Bit
& '1' -- description
& '0' -- ditto
& "01";
Another answer is to write a function to create instructions : this can make the main flow very simple and clear, while keeping the instruction encodings entirely separate and in a single place, e.g. in a package used wherever you need to know the instruction formats (perhaps in an assembler as well as the CPU)
DataOut <= Encode_Instruction(Instr_Defined, Bus_8_Bit, Font_Mode);
It's OK to use any of the preceding techniques, however verbose, in the function body. The more explicit and detailed the better; it isn't cluttering up the main design so you'll rarely look at it unless changing instruction formats.
do this:
DataOut(7 downto 6)<="00";
DataOut(5)<='1';
DataOut(4)<='1';
DataOut(3)<='1';
DataOut(2)<='1';
DataOut(1 downto 0)<="01";