VHDL: genric map setup - vhdl

Why would this setup work?
component mux2to1 is
generic (M : integer := 1); -- Number of bits in the inputs and output
port (input0 : in m32_vector(M-1 downto 0) := (others => '0');
input1 : in m32_vector(M-1 downto 0) := (others => '0');
sel : in m32_1bit;
output : out m32_vector(M-1 downto 0));
end component;
The way I understand genric map is (M: integer: 1) would specify the bit of port to be 1 through out but when M-1 downto 0 would just be 0 down 0, which makes no sense.

As #user1155120 said, you can have an array that has 1 element. (0 downto 0) would have 1 element.
There is another important point to make, however:
In VHDL an array of 1 element of a certain type is not the same type as the element type. So, for example, std_logic and std_logic_vector(0 downto 0) are different types. You cannot assign one to the other. std_logic is a scalar whilst std_logic_vector(0 downto 0) is an array type.
To "convert" between these types, you need to index the array type. So, with signals
signal S : std_logic;
signal A : std_logic_vector(0 downto 0);
you cannot assign A to S or visa versa, but you can do this:
A(0) <= S;
or this:
S <= A(0);
You can also index array ports. So, with
entity HAS_ARRAY_PORT
port ( P : in std_logic_vector(0 downto 0));
end;
You can do this:
L: entity work.HAS_ARRAY_PORT port map (P(0) => S);

Related

Subtracting from all element of an array: VHDL

I am receiving a data. For storing that I have declared an array:
type fifo_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_array: fifo_array := (others => (others => '0'));
During process, this gets filled with different words(bytes). I want to subtract an offset of x30(hex) from all the elements of this array and assign it to another array for further processing. Obviously initializing it like:
type fifo_second_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_second_array: fifo_second_array := (ins_fifo_array - x"30");
not working. There is another solution like:
type fifo_second_array is array(0 to 66) of std_logic_vector(7 downto 0);
signal ins_fifo_second_array: fifo_second_array := (ins_fifo_array(0) - x"30",....);
Which is also not working. Please suggest.
process(ins_fifo_array)
variable I : natural;
constant C_x30 : unsigned := x"30";
begin
for I in 0 to 66 loop
ins_fifo_second_array(I) <= std_logic_vector(unsigned(ins_fifo_array(I)) - C_x30);
end loop;
end process;

VHDL: Instantiated component generic array index out of range

I'm trying to implement an encryption algorithm in VHDL, and I have created a Feedback Shift Register component with generic parameters to improve reusability. It's my first time using generics and arrays, so please bear with me.
This component takes the feedback bits as an input, and it connects some of its bits (taps) to an output port, but this connections can be changed using a generic parameter. Code for the FSR component:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.fsr_taps_type.all;
entity FSR is
generic (
r_WIDTH : integer; -- Register width
r_STEP : integer; -- Update step
r_FWIDTH : integer; -- Feedback output width
r_HWIDTH : integer; -- h-function output width
r_TAPS : TAPS; -- Change the size according to the number of taps
r_STATE : TAPS
);
port (
clk : in std_logic;
rst : in std_logic;
fb_in : in std_logic_vector ((r_STEP-1) downto 0);
init : in std_logic;
ini_data : in std_logic_vector ((r_WIDTH-1) downto 0);
out_data : out std_logic_vector ((r_STEP-1) downto 0);
fb_out : out std_logic_vector ((r_FWIDTH-1) downto 0);
h_out : out std_logic_vector ((r_HWIDTH-1) downto 0)
);
end entity;
architecture behavioural of FSR is
signal shifted,shifted_next : std_logic_vector((r_WIDTH-1) downto 0);
begin
process(clk,rst)
begin
if rst = '1' then
shifted <= (others => '0');
elsif clk'event and clk = '1' then
shifted <= shifted_next;
end if;
end process;
process (fb_in,init,ini_data,shifted)
begin
if init = '1' then
shifted_next <= ini_data;
else
shifted_next <= shifted((r_WIDTH-r_STEP-1) downto 0) & fb_in;
end if;
end process;
out_data <= shifted ((r_WIDTH-1) downto (r_WIDTH-r_STEP));
-- The bits defined in the r_TAPS and r_STATE arrays are connected to the outputs in the same order as they are written (left to right)
-- Example: r_TAPS := (10,6) will create fb_out (1 downto 0) = bit10 & bit 6, in that order
-- Connect taps in the order of r_TAPS
gen_feedback: for I in (r_FWIDTH-1) downto 0 generate
fb_out(I) <= shifted(r_STATE(r_FWIDTH-I-1));
end generate gen_feedback;
-- Connect output bits for h function
gen_h: for I in (r_HWIDTH-1) downto 0 generate
h_out(I) <= shifted(r_STATE(r_HWIDTH-I-1));
end generate gen_h;
end architecture;
My problem comes when instantiating this component twice in the same file, using different generic values. This is the generic map of both instances:
LFSR : FSR
generic map (
r_WIDTH => 128,
r_STEP => STEP,
r_FWIDTH => 6,
r_HWIDTH => 7,
r_TAPS (0 to 5) => (128,121,90,58,47,32),
r_STATE (0 to 6) => (34,49,68,86,108,115,120)
)
NFSR : FSR
generic map (
r_WIDTH => 128,
r_STEP => STEP,
r_FWIDTH => 29,
r_HWIDTH => 2,
r_TAPS (0 to 28) => (40,36,35,33,106,104,103,58,50,46,117,115,111,110,88,80,101,69,67,63,125,61,60,44,128,102,72,37,32),
r_STATE => (33,116)
)
When I only create the first instance, the elaboration works as expected and Vivado gives no error whatsoever. However, when I add the second instance, I get an out of range error:
ERROR: [Synth 8-97] array index 0 out of range (FSR.vhdl:54)
Line 54 is the line inside the first for generate loop:
fb_out(I) <= shifted(r_STATE(r_FWIDTH-I-1));
Only the second instance gives an error. I have tried copying the parameters from the first instance into the second, and I still get the same error.
What am I doing wrong?
EDIT: I added the whole code for the FSR component.
EDIT 2: I changed the type declaration for TAPS, so that the array is constrained:
type TAPS is array (0 to 31) of integer;
This seems to be working, I just have to add an others statement to fill the unused array numbers, so this:
r_TAPS (0 to 5) => (128,121,90,58,47,32)
Becomes this:
r_TAPS (0 to 5) => (128,121,90,58,47,32,others =>0)
As I said before, I'm new to arrays in VHDL, so I would like to know if there is a way to do this for arbitrarily long arrays using an unconstrained array type.

Two dimentional array value to another signal in vhdl

I have created a two dimensional array.
type dataout is array (12 downto 0, 12 downto 0) of std_logic_vector(7 downto 0);
signal a : dataout;
The values are passing through the array and operation like addition and subtraction are also performing but i am not getting the way to pass this value of array to pass through another signal or output port.
Suggest me how to pass these values to another array, signal and output port.
Simply create an output port of type dataout and assign a to it.
To do this, the declaration of dataout must be in a package
package my_types is
type dataout is array (12 downto 0, 12 downto 0) of std_logic_vector(7 downto 0);
end package my_types;
which you use both in this entity/arch and any outer layer that instantiates it.
use work.my_types.all;
entity test is
port(
clock : in std_logic;
a_out : out dataout
);
end test;
architecture t of test is
signal a : dataout;
begin
a_out <= a;
end t;

Using array of std_logic_vector as a port type, with both ranges using a generic

Is it possible to create an entity with a port that is an array of std_logic_vectors, with both the size of the array and the std_logic_vector coming from generics? Ie. is it possible to create eg. a bus multiplexer with both the bus width and bus count configurable?
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in array(integer range 2**sel_width - 1 downto 0) of std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
o <= i(to_integer(unsigned(sel)));
end dataflow;
The above doesn't seem to work because the array type needs to be defined separately.
Defining the type before the port also does not work, as then it expects the entity definition to end after it. Defining it after the port definition doesn't work since it'd be used before that. Defining it in a package doesn't work because the type definition doesn't seem to like having an unconstrained range in the "base type".
Is it possible to somehow do this in VHDL-93? (What about VHDL-2008?)
Defining the type as array(natural range <>, natural range <>) of std_logic in the package works - as in the port definition doesn't give an error - but actually using it if it's defined that way seems to be quite unwieldy.
Is there some sane way to use it like this? Is there some simple way to map N separate std_logic_vectors to a port defined like that, and likewise for the actual output logic?
I tried the original and o <= i(to_integer(unsigned(sel)), bus_width - 1 downto 0), but neither worked. I know I could do it one bit at a time, but I'd prefer something simpler. And while the bit-by-bit -approach might be okay for the internal implementation, I certainly wouldn't want to have to do that for the port mapping every time I use the component...
Is there some sane(-ish) way to do this?
(Addendum: I know there are some similar questions, but most of them don't deal with the case of both ranges coming from generics, and were solved using a type definition in a package. The one that did talk about two generic dimensions apparently didn't need the input to come from distinct std_logic_vectors and ended up using the "2d-array of std_logic" method, which doesn't work for me (at least without further clarification about how to use it without losing one's sanity))
This works with VHDL2008:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package bus_multiplexer_pkg is
type bus_array is array(natural range <>) of std_logic_vector;
end package;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in bus_array(2**sel_width - 1 downto 0)(bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
o <= i(to_integer(unsigned(sel)));
end dataflow;
And it can be used like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer_4 is
generic (bus_width : positive := 8);
port ( bus0, bus1, bus2, bus3 : in std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer_4;
architecture structural of bus_multiplexer_4 is
signal i : bus_array(3 downto 0)(bus_width - 1 downto 0);
begin
i <= (0 => bus0, 1 => bus1, 2 => bus2, 3 => bus3);
u: entity bus_multiplexer generic map (bus_width => bus_width, sel_width => 2) port map (i => i, sel => sel, o => o);
end;
It doesn't work with VHDL93, however, because you can't leave the std_logic_vector unconstrained in the type definition, as stated in the question.
Unfortunately, I don't know if there's any way to do anything similar without 2d arrays with VHDL93.
Edit: Paebbels's answer shows how to do this in VHDL93 by using 2d arrays, with custom procedures to make it manageable. Since his example is quite big, here's also a minimal example of the same concept:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package bus_multiplexer_pkg is
type bus_array is array(natural range <>, natural range <>) of std_logic;
procedure slm_row_from_slv(signal slm : out bus_array; constant row : natural; signal slv : in std_logic_vector);
procedure slv_from_slm_row(signal slv : out std_logic_vector; signal slm : in bus_array; constant row : natural);
end package;
package body bus_multiplexer_pkg is
procedure slm_row_from_slv(signal slm : out bus_array; constant row : natural; signal slv : in std_logic_vector) is
begin
for i in slv'range loop
slm(row, i) <= slv(i);
end loop;
end procedure;
procedure slv_from_slm_row(signal slv : out std_logic_vector; signal slm : in bus_array; constant row : natural) is
begin
for i in slv'range loop
slv(i) <= slm(row, i);
end loop;
end procedure;
end package body;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in bus_array(2**sel_width - 1 downto 0, bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
slv_from_slm_row(o, i, to_integer(unsigned(sel)));
end dataflow;
And it can be used like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer_4 is
generic (bus_width : positive := 8);
port ( bus0, bus1, bus2, bus3 : in std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer_4;
architecture structural of bus_multiplexer_4 is
signal i : bus_array(3 downto 0, bus_width - 1 downto 0);
begin
slm_row_from_slv(i, 0, bus0);
slm_row_from_slv(i, 1, bus1);
slm_row_from_slv(i, 2, bus2);
slm_row_from_slv(i, 3, bus3);
u: entity bus_multiplexer generic map (bus_width => bus_width, sel_width => 2) port map (i => i, sel => sel, o => o);
end;
Yes, it's possible.
Your attempt with a two dimensional array is good, because nested 1 dimensional array need a fixed size in the inner dimensions. So the way to handle such a 2D array is to write some functions and procedures, which convert the 2D array into nested 1D vectors.
I answered a similar question here:
- Fill one row in 2D array outside the process (VHDL) and
- Creating a generic array whose elements have increasing width in VHDL
Here is my vectors package.
And here is an example of an multiplexer for a FIFO interface, which is variable in data width as well as in input count. It uses a round robin arbiter to select the inputs.
Entity 'PoC.bus.Stream.Mux':
-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
--
-- ============================================================================
-- Authors: Patrick Lehmann
--
-- License:
-- ============================================================================
-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
-- Chair for VLSI-Design, Diagnostics and Architecture
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- ============================================================================
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
library PoC;
use PoC.config.all;
use PoC.utils.all;
use PoC.vectors.all;
entity Stream_Mux is
generic (
PORTS : POSITIVE := 2;
DATA_BITS : POSITIVE := 8;
META_BITS : NATURAL := 8;
META_REV_BITS : NATURAL := 2
);
port (
Clock : IN STD_LOGIC;
Reset : IN STD_LOGIC;
-- IN Ports
In_Valid : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_Data : IN T_SLM(PORTS - 1 downto 0, DATA_BITS - 1 downto 0);
In_Meta : IN T_SLM(PORTS - 1 downto 0, META_BITS - 1 downto 0);
In_Meta_rev : OUT T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0);
In_SOF : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_EOF : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_Ack : OUT STD_LOGIC_VECTOR(PORTS - 1 downto 0);
-- OUT Port
Out_Valid : OUT STD_LOGIC;
Out_Data : OUT STD_LOGIC_VECTOR(DATA_BITS - 1 downto 0);
Out_Meta : OUT STD_LOGIC_VECTOR(META_BITS - 1 downto 0);
Out_Meta_rev : IN STD_LOGIC_VECTOR(META_REV_BITS - 1 downto 0);
Out_SOF : OUT STD_LOGIC;
Out_EOF : OUT STD_LOGIC;
Out_Ack : IN STD_LOGIC
);
end;
architecture rtl OF Stream_Mux is
attribute KEEP : BOOLEAN;
attribute FSM_ENCODING : STRING;
subtype T_CHANNEL_INDEX is NATURAL range 0 to PORTS - 1;
type T_STATE is (ST_IDLE, ST_DATAFLOW);
signal State : T_STATE := ST_IDLE;
signal NextState : T_STATE;
signal FSM_Dataflow_en : STD_LOGIC;
signal RequestVector : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal RequestWithSelf : STD_LOGIC;
signal RequestWithoutSelf : STD_LOGIC;
signal RequestLeft : UNSIGNED(PORTS - 1 downto 0);
signal SelectLeft : UNSIGNED(PORTS - 1 downto 0);
signal SelectRight : UNSIGNED(PORTS - 1 downto 0);
signal ChannelPointer_en : STD_LOGIC;
signal ChannelPointer : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal ChannelPointer_d : STD_LOGIC_VECTOR(PORTS - 1 downto 0) := to_slv(2 ** (PORTS - 1), PORTS);
signal ChannelPointer_nxt : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal ChannelPointer_bin : UNSIGNED(log2ceilnz(PORTS) - 1 downto 0);
signal idx : T_CHANNEL_INDEX;
signal Out_EOF_i : STD_LOGIC;
begin
RequestVector <= In_Valid AND In_SOF;
RequestWithSelf <= slv_or(RequestVector);
RequestWithoutSelf <= slv_or(RequestVector AND NOT ChannelPointer_d);
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
State <= ST_IDLE;
else
State <= NextState;
end if;
end if;
end process;
process(State, RequestWithSelf, RequestWithoutSelf, Out_Ack, Out_EOF_i, ChannelPointer_d, ChannelPointer_nxt)
begin
NextState <= State;
FSM_Dataflow_en <= '0';
ChannelPointer_en <= '0';
ChannelPointer <= ChannelPointer_d;
case State is
when ST_IDLE =>
if (RequestWithSelf = '1') then
ChannelPointer_en <= '1';
NextState <= ST_DATAFLOW;
end if;
when ST_DATAFLOW =>
FSM_Dataflow_en <= '1';
if ((Out_Ack AND Out_EOF_i) = '1') then
if (RequestWithoutSelf = '0') then
NextState <= ST_IDLE;
else
ChannelPointer_en <= '1';
end if;
end if;
end case;
end process;
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
ChannelPointer_d <= to_slv(2 ** (PORTS - 1), PORTS);
elsif (ChannelPointer_en = '1') then
ChannelPointer_d <= ChannelPointer_nxt;
end if;
end if;
end process;
RequestLeft <= (NOT ((unsigned(ChannelPointer_d) - 1) OR unsigned(ChannelPointer_d))) AND unsigned(RequestVector);
SelectLeft <= (unsigned(NOT RequestLeft) + 1) AND RequestLeft;
SelectRight <= (unsigned(NOT RequestVector) + 1) AND unsigned(RequestVector);
ChannelPointer_nxt <= std_logic_vector(ite((RequestLeft = (RequestLeft'range => '0')), SelectRight, SelectLeft));
ChannelPointer_bin <= onehot2bin(ChannelPointer);
idx <= to_integer(ChannelPointer_bin);
Out_Data <= get_row(In_Data, idx);
Out_Meta <= get_row(In_Meta, idx);
Out_SOF <= In_SOF(to_integer(ChannelPointer_bin));
Out_EOF_i <= In_EOF(to_integer(ChannelPointer_bin));
Out_Valid <= In_Valid(to_integer(ChannelPointer_bin)) and FSM_Dataflow_en;
Out_EOF <= Out_EOF_i;
In_Ack <= (In_Ack 'range => (Out_Ack and FSM_Dataflow_en)) AND ChannelPointer;
genMetaReverse_0 : if (META_REV_BITS = 0) generate
In_Meta_rev <= (others => (others => '0'));
end generate;
genMetaReverse_1 : if (META_REV_BITS > 0) generate
signal Temp_Meta_rev : T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0) := (others => (others => 'Z'));
begin
genAssign : for i in 0 to PORTS - 1 generate
signal row : STD_LOGIC_VECTOR(META_REV_BITS - 1 downto 0);
begin
row <= Out_Meta_rev AND (row'range => ChannelPointer(I));
assign_row(Temp_Meta_rev, row, i);
end generate;
In_Meta_rev <= Temp_Meta_rev;
end generate;
end architecture;

VHDL multiple constant drivers

I'm trying to modify a source code for do a sum (for example) and other maths function using switch and hex display.
This is the main code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.seven_segment_pkg.all;
entity Switch7Segment is
port (
SW : in std_logic_vector(9 downto 0);
HEX0 : out std_logic_vector(6 downto 0);
HEX1 : out std_logic_vector(6 downto 0);
HEX2 : out std_logic_vector(6 downto 0);
HEX3 : out std_logic_vector(6 downto 0);
KEY : in std_logic_vector(3 downto 0);
CLOCK_50 : in std_logic
);
end entity Switch7Segment;
architecture behavior of Switch7Segment is
signal segments1 : std_logic_vector(13 downto 0);
signal segments2 : std_logic_vector(13 downto 0);
signal segmentsR : std_logic_vector(13 downto 0); -- Range changed from 27 downto 0 to allow compile
signal input1 : integer;
signal input2 : integer;
signal result : unsigned(31 downto 0); -- Range added to allow compile
signal temp : integer;
begin
input1 <= to_integer(unsigned(SW(4 downto 0)));
input2 <= to_integer(unsigned(SW(9 downto 5)));
segments1 <= unsigned_to_seven_segment(value => unsigned(SW(4 downto 0)), number_of_digits => 2, value_is_bcd => false);
segments2 <= unsigned_to_seven_segment(value => unsigned(SW(9 downto 5)), number_of_digits => 2, value_is_bcd => false);
HEX1 <= segments1(13 downto 7);
HEX0 <= segments1(6 downto 0);
HEX3 <= segments2(13 downto 7);
HEX2 <= segments2(6 downto 0);
process(CLOCK_50)
begin
if (CLOCK_50' EVENT and CLOCK_50 = '1' AND KEY(0) = '1') then
temp <= input1+input2;
result <= to_unsigned(integer(temp), result'length);
segmentsR <= unsigned_to_seven_segment(value => unsigned(result), number_of_digits => 2, value_is_bcd => false);
HEX1 <= segmentsR(13 downto 7);
HEX0 <= segmentsR(6 downto 0);
end if;
end process;
end architecture;
And then there is the package:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package seven_segment_pkg is
-- Return a std_logic_vector ready for driving a number of 7-segment displays.
function unsigned_to_seven_segment(value : unsigned; number_of_digits : integer; value_is_bcd : boolean)
return std_logic_vector;
end;
package body seven_segment_pkg is
function seven_seg_from_bcd_digit(bcd_digit : std_logic_vector(3 downto 0)) return std_logic_vector is
begin
case bcd_digit is
-- abcdefg
when x"0" => return "1000000";
when x"1" => return "1111001";
when x"2" => return "0100100";
when x"3" => return "0110000";
when x"4" => return "0011001";
when x"5" => return "0010010";
when x"6" => return "0000010";
when x"7" => return "1111000";
when x"8" => return "0000000";
when x"9" => return "0010000";
when x"a" => return "0001000";
when x"b" => return "0000011";
when x"c" => return "1000110";
when x"d" => return "0100001";
when x"e" => return "0000110";
when x"f" => return "1110001";
when others => return "0000000";
end case;
end function;
-- Return a vector ready for driving a series of 7-segment displays.
function unsigned_to_seven_segment(
value : unsigned;
-- Number of 7-segment displays (determines output vector width: W = 7*N)
number_of_digits : integer;
-- When true, treat the input value as a BCD number where every 4 bits hold one
-- digit from 0 to A. When false, treat the input number as an unsigned integer.
value_is_bcd : boolean
) return std_logic_vector is
variable segments : std_logic_vector(number_of_digits*7-1 downto 0);
variable bcd_quotient : unsigned(value'range);
variable bcd_remainder : unsigned(3 downto 0);
begin
if value_is_bcd then
for i in 0 to number_of_digits-1 loop
segments(i*7+6 downto i*7) := seven_seg_from_bcd_digit(
std_logic_vector(value(i*4+3 downto i*4))
);
end loop;
else
bcd_quotient := value;
for i in 0 to number_of_digits-1 loop
bcd_remainder := resize(bcd_quotient mod 10, 4);
bcd_quotient := bcd_quotient / 10;
segments(i*7+6 downto i*7) := seven_seg_from_bcd_digit(
std_logic_vector(bcd_remainder)
);
end loop;
end if;
return segments;
end function;
end package body;
I think that there is an error that at the moment i never signed here that is the length of the result. if we compile this VHDL code Quartus will tell us that the function is for 13 element and not for 27. But i don't see an obstacle to resolve it....my problem is about outputs (HEX0.....HEX3)
If i modify the code and i insert
signal segmentsR: std_logic_vector(13 downto 0);
I resolve the problem of the length but i will see error 10028 (multiple constant drivers).
If i understood correct, i can't assign two times at the same vector two different value or something similar is correct? maybe i always think like a C++ / C programmer. I think that if i use CLOCK the problem will be resolve but is not true...
The problem is that there are drivers for HEX0 and HEX1 both before the process and in the process, but any signal/port should only be driven from one place in typical synthesized code.
If the HEX0 and HEX1 are driven from the process, then remove the drivers before the process.
Conceptually, a multiple drivers error means that your behavioral code (remember: VHDL describes how a circuit works) isn't able to be synthesized. Or, if you have really special synthesizing code, it will give you unexpected results.
In my experience, this error results when I write code with undefined behavior -- for example, if in two processes I modify the same variable (say, X) based on some condition, then the hardware could run into an undefined state where both conditions are met -- how should the variable be modified? If you are familiar to race conditions or mutual exclusion, this should look familiar. Hardware languages don't have easy support for mutex and the like, so they warn you and won't let you do the bad thing.
In your case, I think you could clarify your code and simplify things by assigning default values to your top-level ports, like so:
entity Switch7Segment is
port (
SW : in std_logic_vector(9 downto 0);
HEX0 : out std_logic_vector(6 downto 0);
HEX1 : out std_logic_vector(6 downto 0) := (others => '0');
HEX2 : out std_logic_vector(6 downto 0) := (others => '0');
HEX3 : out std_logic_vector(6 downto 0);
KEY : in std_logic_vector(3 downto 0);
CLOCK_50 : in std_logic
);
end entity Switch7Segment;
This provides a default value for an entity. Whatever creates the entity can provide a different value than the default. Read more here: http://vhdl.renerta.com/mobile/source/vhd00051.htm
It looks like your default value is more complicated (based on the inputs of the function). In this case, I would either (1) change my interface so that the caller provides the information or (2) write a function and a constant in a package and use the function/constant as the default value.
Another possible solution is using generics and default value. This would let you use the bits of the SW field in you default values. (ie: something like HEX2 : out std_logic_vector(6 downto 0) := (SW(xx downto yy), where SW is defined in the generics port)

Resources