VHDL, how does concatenate work? - vhdl

I have some code in VHDL. I don't understand how concatenation works.
A : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
B : IN IN STD_LOGIC;
A <= "1111";
B <= '0';
A <= A(2 DOWNTO 0) & B;
Is A "0111" or "1110"?

As far as the concatenation itself is concerned, you seem to be doing that right, but apart from the other errors (you're assigning to an input, as BrianDrummond noted, and you've not got compilable syntax), you'll have a problem because VHDL signal assignments outside of a process are concurrent (i.e. they are evaluated continuously and in parallel).
So if you do:
A <= "1111";
A <= A(2 DOWNTO 0) & B;
You'll be assigning every bit of A with two drivers - a '1', and the bit on the left of it except for the least significant bit which gets assigned 'B'. Imagine constructing this with actual copper wires. You are tying all bits of A together - AND tying them to the positive voltage source.
If B is '1' this should resolve to all '1', but if B is '0' you will effectively connect the positive and negative voltage terminals, like a short circuit. Your simulator will tell you the result is 'X' - unknown.

Related

Assigning initial value to VHDL vector

I am just learning the syntax of VHDL
I'd like to assign an initial value of '1' to Qout(0) and the rest '0'.
I cannot find the reference that shows me the correct syntax.
This gave me an error:
signal Qout: Std_Logic_Vector (4 downto 0) :='1';
As user1155120 says, in VHDL the width of the right hand side has to match the width of the left hand side of an assignment operator (<= or :=).
So, you could use the literal that corresponds to a std_logic_vector, which is a string:
signal Qout: Std_Logic_Vector (4 downto 0) := "00001";
(a string literal in VHDL is enclosed within double quotes). Or (and this is what a more experience VHDL user would do) use an aggregate:
signal Qout: Std_Logic_Vector (4 downto 0) := (0 => '1', others => '0');
The construct on the right hand side is an aggregate. An aggregate is a construct for representing composite data types such as arrays (which is what a std_logic_vector is) and record types (like a struct in C). The above example is saying "make element 0 equal to '1' and make all the other elements equal to '0'. Element 0 is the right hand side, because the array was declared (4 downto 0) (not (0 to 4)).
Using an aggregate might be considered a better way of doing it because, whilst not to clear to a beginner, the code is more maintainable: if the width of the signal were to change, you would not have to modify the aggregate.
You might want to seriously consider why you want to initialise this signal at all. If you are using an FPGA, it may be the case that that the corresponding flip-flops will be initialised as you wish. (I assume this signal Qout will become 5 flip-flops because of the name you have chosen.) On a chip this would never ever be the case - your initialisation would be ignored. You might want to consider whether providing a reset to your flip-flops would be a better solution than initialising a signal, eg an active-high synchronous reset:
process (Clock)
begin
if Reset = '1' then
Qout <= (0 => '1', others => '0');
elsif rising_edge(Clock) then
...

Multiplier via Repeated Addition

I need to create a 4 bit multiplier as a part of a 4-bit ALU in VHDL code, however the requirement is that we have to use repeated addition, meaning if A is one of the four bit number and B is the other 4 bit number, we would have to add A + A + A..., B number of times. I understand this requires either a for loop or a while loop while also having a temp variable to store the values, but my code just doesn't seem to be working and I just don't really understand how the functionality of it would work.
PR and T are temporary buffer standard logic vectors and A and B are the two input 4 bit numbers and C and D are the output values, but the loop just doesn't seem to work. I don't understand how to loop it so it keeps adding the A bit B number of times and thus do the multiplication of A * B.
WHEN "010" =>
PR <= "00000000";
T <= "0000";
WHILE(T < B)LOOP
PR <= PR + A;
T <= T + 1;
END LOOP;
C <= PR(3 downto 0);
D <= PR(7 downto 4);
This will never work, because when a line with a signal assignment (<=) like this one:
PR <= PR + A;
is executed, the target of the signal assignment (PR in this case) is not updated immediately; instead an event (a future change) is scheduled. When is this event (change) actioned? When all processes have suspended (reached wait statements or end process statements).
So, your loop:
WHILE(T < B)LOOP
PR <= PR + A;
T <= T + 1;
END LOOP;
just schedules more and more events on PR and T, but these events never get actioned because the process is still executing. There is more information here.
So, what's the solution to your problem? Well, it depends what hardware you are trying to achieve. Are you trying to achieve a block of combinational logic? Or sequential? (where the multiply takes multiple clock cycles)
I advise you to try not to think in terms of "temporary variables", "for loops" and "while loops". These are software constructions that can be useful, but ultimately you are designing a piece of hardware. You need to try to think about what physical pieces of hardware can be connected together to achieve your design, then how you might describe them using VHDL. This is difficult at first.
You should provide more information about what exactly you want to achieve (and on what kind of hardware) to increase the probability of getting a good answer.
You don't mention whether your multiplier needs to operate on signed or unsigned inputs. Let's assume signed, because that's a bit harder.
As has been noted, this whole exercise makes little sense if implemented combinationally, so let's assume you want a clocked (sequential) implementation.
You also don't mention how often you expect new inputs to arrive. This makes a big difference in the implementation. I don't think either one is necessarily more difficult to write than the other, but if you expect frequent inputs (e.g. every clock cycle), then you need a pipelined implementation (which uses more hardware). If you expect infrequent inputs (e.g. every 16 or more clock cycles) then a cheaper serial implementation should be used.
Let's assume you want a serial implementation, then I would start somewhere along these lines:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity loopy_mult is
generic(
g_a_bits : positive := 4;
g_b_bits : positive := 4
);
port(
clk : in std_logic;
srst : in std_logic;
-- Input
in_valid : in std_logic;
in_a : in signed(g_a_bits-1 downto 0);
in_b : in signed(g_b_bits-1 downto 0);
-- Output
out_valid : out std_logic;
out_ab : out signed(g_a_bits+g_b_bits-1 downto 0)
);
end loopy_mult;
architecture rtl of loopy_mult is
signal a : signed(g_a_bits-1 downto 0);
signal b_sign : std_logic;
signal countdown : unsigned(g_b_bits-1 downto 0);
signal sum : signed(g_a_bits+g_b_bits-1 downto 0);
begin
mult_proc : process(clk)
begin
if rising_edge(clk) then
if srst = '1' then
out_valid <= '0';
countdown <= (others => '0');
else
if in_valid = '1' then -- (Initialize)
-- Record the value of A and sign of B for later
a <= in_a;
b_sign <= in_b(g_b_bits-1);
-- Initialize countdown
if in_b(g_b_bits-1) = '0' then
-- Input B is positive
countdown <= unsigned(in_b);
else
-- Input B is negative
countdown <= unsigned(-in_b);
end if;
-- Initialize sum
sum <= (others => '0');
-- Set the output valid flag if we're already finished (B=0)
if in_b = 0 then
out_valid <= '1';
else
out_valid <= '0';
end if;
elsif countdown > 0 then -- (Loop)
-- Let's assume the target is an FPGA with efficient add/sub
if b_sign = '0' then
sum <= sum + a;
else
sum <= sum - a;
end if;
-- Set the output valid flag when we get to the last loop
if countdown = 1 then
out_valid <= '1';
else
out_valid <= '0';
end if;
-- Decrement countdown
countdown <= countdown - 1;
else
-- (Idle)
out_valid <= '0';
end if;
end if;
end if;
end process mult_proc;
-- Output
out_ab <= sum;
end rtl;
This is not immensely efficient, but is intended to be relatively easy to read and understand. There are many, many improvements you could make depending on your requirements.

How does this SIPO Works?

I am making an UART transceiver, and In that for Receiver section, I need a SIPO to convert the serial data into parallel one, A web search threw out a code which does the required function, I am not able to understand how this particular code works, googling didn't help. I am grateful if someone can point out how this works
library ieee;
use ieee.std_logic_1164.all;
entity RXN_CNTRL is
port(
reset : in std_logic;
clk : in std_logic;
din : in std_logic;
dout : out std_logic_vector(3 downto 0)
);
end entity;
architecture behave of RXN_CNTRL is
signal s : std_logic_vector(3 downto 0) := "0000" ;
begin
sipo : process (clk, reset)
begin
if (reset='1') then
s <= "0000";
elsif (rising_edge (clk)) then
s <= (din & s(3 downto 1));
end if;
end process;
dout <= s;
end architecture;
I am not able to understand how the line s <= (din & s(3 downto 1));
works. please clear me in this, I am new to vhdl and want to learn how this works. Thanks
In VHDL & is the concatenation operator. It is used to make bigger arrays from smaller arrays and single array elements by concatenating them, ie joining them together. So,
s <= (din & s(3 downto 1));
takes the single bit din and joins it to the leftmost 3 bits of s (s(3 downto 1)) to give a new value of s:
din s(3) s(2) s(1)
So, you can see that s has been shifted one place to the right and the empty space has been filled with din - exactly the behaviour you'd want for a SIPO.
In VHDL I would recommend always using the combination of concatenation and slicing (taking part of an array, like s(3 downto 1)) for implementing shift-registers and so on. The builtin operators (sla etc) behave in strange ways.
& is the concatenation operator in VHDL.
So what this does is to shift in the newly received bit (din) into s from the left (disposing the lowest bit of s).
Suppose s is "0000" initially. If din = '1', then s <= din & s(3 downto 1) takes din ('1'), concatenates s(3 downto 1)("000") to it and assigns the result to s. The lowest bit of s is 'lost' through this.
I recommend playing through this until you understand what happens.

VHDL Is there a cleaner way to set specific bit, given the bit number?

Given a bit number, I am trying to set that bit in a std_logic_vector. This is for toggling various clock outputs one at a time.
First of all, I've completely given up on sll, or SHIFT_LEFT which seems to be the obvious way to do it, but which totally doesn't work at all.
variable v_cmd_clk_1: std_logic_vector(11 downto 0);
...
--- set bit number "s_proc_chan", plus 4, in v_cmd_clk_1
v_cmd_clk_1 := "0000" & "0000" & "0000";
v_cmd_clk_1( to_integer ( unsigned(s_proc_chan(2 downto 0))) + 4 ) := '1';
...
-- And then later on in the process assign it to an actual signal
cmd_clk <= v_cmd_clk_0;
Is there a better or cleaner syntax for doing this?
Thanks.
Three suggestions for you. First one uses aggregates:
v_cmd_clk_1 <= (to_integer(unsigned(s_proc_chan(2 downto 0)))+4) => '1', others => '0');
Second one uses integer to unsigned conversion:
v_cmd_clk_1 <= std_logic_vector(to_unsigned(2**(to_integer(unsigned(s_proc_chan(2 downto 0)))+4)); -- No guarantee on parentheses matching
Third one, using shift_left:
v_cmd_clk_1 <= std_logic_vector(shift_left(resize(unsigned'("1"), v_cmd_clk_1'length), to_integer(unsigned(s_proc_chan(2 downto 0)))+4));
The principle of setting a single bit given by index, as you already done, is fine, and it shows the intention of the code, which is setting a bit given by an index.
It would be possible to eliminate the + 4 offset through use of other std_logic_vector ranges, but a decent synthesis tool eliminates the offset, so an add operation is not implemented.
Anyhow, as answer to the comment, the + 4 can be eliminated if a std_logic_vector is addressed directly into 0 to 7, instead of addressing 4 to 11, and the last 4 '0's can just be postpended, like:
variable v_cmd_clk_1 : std_logic_vector(11 downto 0);
variable v_cmd_clk_upper: std_logic_vector( 7 downto 0);
...
v_cmd_clk_upper := (others => '0');
v_cmd_clk_upper(to_integer(unsigned(s_proc_chan(2 downto 0)))) := '1';
v_cmd_clk_1 := v_cmd_clk_upper & "0000";
The aggregate suggested by Jonathan Drolet looks nice, but for example Altera Quartus II won't allow this for synthesis, since it requires constant choice values in aggregates. Using shift or 2** will synthesize.
Note that initial clearing is more general with:
v_cmd_clk_1 := (others => '0');

Split n long bit logic vector to n individual binary values

I was wondering if there was a method where you can split a n bit long vector for example:
10100111
Into n individual binary units to be used later on? I'm trying to incorporate a method where i can get a 8 bit long vector and have 8 LED's light up depending if that n'th value is 0 or 1. Googling the question returns people cutting up a larger vector into smaller ones, but if we were to have 16 bits for example then i'd have to make 16 separate variables for it work using:
entity test is
port (
myVector : in std_logic_vector(16 downto 0);
LED : out std_logic_vector(16 downto 0)
);
END test
architecture behavior of test is
SIGNAL led1 : std_logic;
...
SIGNAL led16 : std_logic;
BEGIN
led1 <= myVector(0);
...
led16 <= myVector(16);
LED(1) <= '1' when led1 = '1' else '0';
...
LED(16) <= '1' when led16 = '1' else '0';
END behavior
Doesn't seem tidy when it needs to be repeated several times in the code.
If you want to declare and assign to identifiers with different names, then you have to make a line for each name, since there is no loop statement for identifier name manipulation in VHDL.
But VHDL provides arrays, where you can loop over the entries, like with this example code:
...
signal led_sig : std_logic_vector(16 downto 0);
begin
loop_g: for idx in myVector'range generate
led_sig(idx) <= myVector(idx);
LED(idx) <= '1' when led_sig(idx) = '1' else '0';
end generate;
...
Where the assigns are equivalent to the shorter:
led_sig <= myVector;
LED <= led_sig;

Resources