Suppose I have an alias for a a single bit or number of bits in a std_logic_vector declared such as this:
signal CR : std_logic_vector(7 downto 0);
alias CR_ARM : std_logic is CR(0);
alias CR_PS : std_logic_vector(3 downto 0) is CR(7 downto 4);
How can I access the range or position of the alias such as:
singal tmp : std_logic_vector(7 downto 0); -- output bus vector
tmp(CR_ARM'range) <= CR_ARM; -- does not compile
Range is only defined for array types. Even when VHDL-2017 will add ranges for scalar types, it won't solve your problem, because you want to know for which bit the alias was created.
Aliases are transparent in VHDL. There is no mechanism to reflect about aliases.
You could use this workaround, which doesn't look very nice:
signal CR : std_logic_vector(7 downto 0);
alias CR_ARM : std_logic_vector is CR(0 downto 0);
signal tmp : std_logic_vector(7 downto 0); -- output bus vector
-- now a slice name works
tmp(CR_ARM'range) <= CR_ARM;
Your second example won't work as expected. You should declare the alias with the same range constraints otherwise you will assign other bits when you use CR_PS'range.
Related
I have a signal dataIn : std_logic_vector ( 15 downto 0);
I want to give an input less than 16-bits for example dataIn <= x"000a" and those bits occupy the most significant bits and the rest to be zero.
In verilog you can do that very easy but in VHDL you get the error:
"string length does not match that of the anonymous integer subtype defined t... ".
I know that if you use 16x"bit_string" solves the problem but this is only for VHDL-2008 and ghdl doesn't support yet VHDL-2008.
Are there any method for IEEE Std 1076-2002?
For VHDL-87/93/2002 you could use the resize function from the numeric_std package.
library ieee;
use ieee.numeric_std.all;
...
constant FOO : std_logic_vector(2 downto 0) := "010";
signal dataIn : std_logic_vector(15 downto 0) := std_logic_vector(resize(unsigned(FOO), 16));
Note that the resize function is only defined for types signed and unsigned.
If you want the short bit string to be placed into the MSBs you may need to use the 'reverse_order attribute.
Often you will find it easier to define a dedicated function which encapsulates more complicated initializations.
constant FOO : std_logic_vector(2 downto 0) := "010";
function init_dataIn (bar : std_logic_vector; len : integer) return std_logic_vector is
begin
return bar & (len - bar'length - 1 downto 0 => '0');
end function init_dataIn;
signal dataIn : std_logic_vector(15 downto 0) := init_dataIn(FOO, 16);
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;
How do I split 16-bit data into 2 8-bit data?
signal part : std_logic_vector (16 downto 0);
signal part_1 : std_logic_vector (8 downto 0);
signal part_2 : std_logic_vector (8 downto 0);
The part is actually 17 bit, since 16 downto 0 is a 17 bit range, and the part_* are likewise 9 bit.
If the ranges are 15 downto 0 and 7 downto 0, then you can do the split with:
part_1 <= part( 7 downto 0);
part_2 <= part(15 downto 8);
Btw, quote by Martin Fowler / Phil Karlton:
There are two hard things in computer science:
cache invalidation, naming things, and off-by-one errors.
Why are your signals 17 bits and 9 bits long? I think they should be 16 and 8...
signal part : std_logic_vector (15 downto 0);
signal part_1 : std_logic_vector (7 downto 0);
signal part_2 : std_logic_vector (7 downto 0);
begin -- architecture begin
part_1 <= part(15 downto 8);
part_2 <= part(7 downto 0);
Pretty simple stuff... I'm surprised you didn't run across this in looking at a VHDL example.
There's also aggregate target assignment:
library ieee;
use ieee.std_logic_1164.all;
entity foo is
end entity;
architecture fum of foo is
type fie is array (natural range 0 to 1) of std_logic_vector (7 downto 0);
signal part: std_logic_vector (15 downto 0);
signal part_1: std_logic_vector (7 downto 0);
signal part_2: std_logic_vector (7 downto 0);
begin
(part_1, part_2) <= fie'(part(15 downto 8), part(7 downto 0));
end architecture;
Which is admittedly more useful for extracting elements of records in one fell swoop. What's slick here is that there's no place there's any named signal of type fie.
The reason for the aggregate on the right hand side is because the element size has to match on both sides of the assignment operator, both aggregates are treated as if they are type fie.
Doing this with records allows you to extract elements of varying sizes. Extracting fields from CPU machine instruction formats comes to mind. It allows you to use simple names without requiring aliases for element selected names. (There would be no named record).
When the element size is the same on both sides you can simply use a target aggregate:
library ieee;
use ieee.std_logic_1164.all;
entity fie is
end entity;
architecture fum of fie is
signal part: std_logic_vector (2 downto 0);
signal part_1: std_logic;
signal part_2: std_logic;
signal part_3: std_logic;
begin
(part_1, part_2, part_3) <= part;
end architecture;
These aggregates all use positional association. You can also use named association. Record aggregates require an others choice represent at least one element and all the elements have to have the same type (e.g. std_logic_vector).
Just for completeness: you can also use aliases which makes the signal assignment obsolete:
signal part : std_logic_vector (15 downto 0);
alias part_1 : std_logic_vector(7 downto 0) is part(15 downto 8);
alias part_2 : std_logic_vector(7 downto 0) is part(7 downto 0);
This has me bugging for quite some time, but is it possible to describe entities in VHDL similar to how templates work in C++ (or to lesser extend generics?). Simply leaving the actual port types to be only decided during synthesize/compilation?
An example would be a multiplexer, say I have a 4 input multiplexer, now I have several bus sizes I use this multiplexer for, -4,6,7,8-. Currently I wrote a different multiplexer for each different bus size; however the output is simply one of the chosen inputs forwarded, and is thus of the same type as the bus.
This seems overly redundant and error prone (choose correct multiplexer at correct times, keep them all in line, update them as I change the bus size). Is there no way to parameterize this?
non generic version below to show the idea.
entity mux_6bit_4input is
port ( input_0 : in std_logic_vector (5 downto 0);
input_1 : in std_logic_vector (5 downto 0);
input_2 : in std_logic_vector (5 downto 0);
input_3 : in std_logic_vector (5 downto 0);
sel : in std_logic_vector (1 downto 0);
output : out std_logic_vector (5 downto 0)
);
end entity mux_6bit_4input;
Maybe I misunderstood the question, but doesn't the common solution using generics solve your problem?
library ieee;
use ieee.std_logic_1164.all;
entity mux_4x1 is
generic (
DATA_WIDTH: integer := 8
);
port (
input_0: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_1: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_2: in std_logic_vector(DATA_WIDTH-1 downto 0);
input_3: in std_logic_vector(DATA_WIDTH-1 downto 0);
sel: in std_logic_vector (1 downto 0);
output: out std_logic_vector(DATA_WIDTH-1 downto 0)
);
end;
architecture behavior of mux_4x1 is
begin
output <=
input_0 when sel = "00" else
input_1 when sel = "01" else
input_2 when sel = "10" else
input_3;
end;
Another solution, if you want to keep things really generic, is to use the cool generic types in VHDL-2008. My simulator doesn't yet support this feature, so here's an example from the excellent book VHDL 2008: Just the New Stuff:
entity generic_mux2 is
generic (type data_type);
port (
sel: in bit;
a, b: in data_type;
z: out data_type
);
end;
architecture rtl of mux2 is
begin
z <= a when sel = '0' else b;
end;
Another option is to use unconstrained arrays:
entity mux_4input is
port (
input_0 : in std_logic_vector ;
input_1 : in std_logic_vector ;
input_2 : in std_logic_vector ;
input_3 : in std_logic_vector ;
sel : in std_logic_vector (1 downto 0);
output : out std_logic_vector
);
end entity mux_4input;
They will inherit their width (and direction) from the signals they are conencted to in the instantiating entity.
It's probably not the right thing to do in this particular case of a mux, rick's answer is what I'd go for, but unconstrained arrays don't get mentioned much, so I thought I'd offer them! In this case, you'd probably also want some asserts to ensure that everything you've wired up is the same width.
I'm developing a little thing in VHDL and am quite new to it. I'm having trouble figuring out how to slice a bigger std_logic_vector into a smaller one.
For instance I have 3 signals:
signal allparts: std_logic_vector(15 downto 0);
signal firstpart: std_logic_vector(7 downto 0);
signal secondpart: std_logic_vector(7 downto 0);
Basically, what I want is to assign bits 15 through 8 to secondpart and bits 7 through 0 to firstpart. How exactly would I "slice" a vector like this without assigning individual bits
You can directly assign them:
firstpart <= allparts(15 downto 8);
secondpart <= allparts(7 downto 0);
...or if firstpart and secondpart are simply alternate ways to refer to part of the allparts signal, you may want to use an alias:
alias firstpart is allparts(15 downto 8);
alias secondpart is allparts(7 downto 0);