Signed Addition overflow in VHDL - vhdl

I tried to implement and addition of two signed numbers. The first one is 32 bit and the second one is also 32 bit, but correspond the addition of the earlier operation. The code VHLD is below :
Entity Sum_Position is
port
(
Clk: in std_logic;
Reset: in std_logic;
Raz_position: in std_logic;
Position_In: in std_logic_vector(31 downto 0);
Position_Out: out std_logic_vector(31 downto 0)
);
end Sum_Position;
Architecture Arch_position of sum_Position is
-- create locale signals
signal position_before: signed (31 downto 0):= (OTHERS => '0');
-- both signals have one more bit than the original
signal Position_s : SIGNED(Position_In'length downto 0):= (OTHERS => '0');
signal Position_Before_s : SIGNED(Position_In'length downto 0):= (OTHERS => '0');
signal Sum_Pos_s : SIGNED(Position_In'length downto 0):= (OTHERS => '0');
Begin -- begin of architecture
-- convert type and perform a sign-extension
Position_s <=SIGNED(Position_In(31) & Position_In);
Position_Before_s<=resize(signed(position_before), Position_Before_s'length);
Sum_of_position: process(Clk, Reset)
begin
IF (Reset='0') THEN -- when reset is selected
-- initialize all values
Sum_Pos_s<= (OTHERS => '0');
ELSIF (Clk'event and Clk = '1') then
-- addition of two 33 bit values
Sum_Pos_s <= Position_s + Position_Before_s;
END IF;
end process Sum_of_position;
-- resize to require size and type conversion
position_before <= (OTHERS => '0') WHEN Raz_position='1' else
signed(resize(Sum_Pos_s, position_before'length));
-- Resize and output the result
Position_Out <= (OTHERS => '0') WHEN Raz_position='1' else
std_logic_vector(resize(Sum_Pos_s, Position_Out'length));
end Arch_position;
But, i have overflow because the result is very strange. Can you please suggest me a solution?
Best regards;

First of all your code is quite unclear.
Secondly, there is no reason for position_before(_s) to be asynchronous, it should be clocked, e.g. (summarized):
begin
IF (Reset='0') THEN -- when reset is selected
-- initialize all values
Sum_Pos_s<= (OTHERS => '0');
ELSIF (Clk'event and Clk = '1') then
Position_Before_s <= Sum_Pos_s
Sum_Pos_s <= Position_s + Position_Before_s;
END IF;
end process Sum_of_position;
Thirdly, the answer to your question. You pass floats to your VHDL engine. Interprete them as signed and add them. You should look at IEEE754 floats. There is a fixed field for the sign bit, one for the exponent and one for the mantissa. You can't just add everything up.
Step 1 is to express both on the same exponent basis. Then add the adjusted mantissas and keep the exponent. Then rescale the mantissa for the most significant bit to correspond to 0.5.
What you to is the following:
0.4 + 40 = (0.1) * 4 + (10) * 4
mantissas are both 4
exponents are -1 and 1. without fields overflowing, your result becomes an exponent of 0 and a mantissa of 8, so 8.

Most modern VHDL tools have Integer types (signed and unsigned).
These are usually 32 bits wide unless you use the Range modifier.
I suggest you consider using integers rather than std_logic_vector.
You can convert between types like casts in C.
This is my favourite diagram on casting/ converting VHDL types. I have printed it out and put it on my wall http://www.bitweenie.com/listings/vhdl-type-conversion
A page in integers in VHDL http://vhdl.renerta.com/mobile/source/vhd00039.htm

Related

Average operation on signed signals in VHDL

I'm trying to calculate the average of a signal on 4 consecutive values. This signal is signed and I'm really not sure about the right calculation to do.
SIGNAL my_signed_signal : std_logic_vector(15 DOWNTO 0) := (OTHERS => '0');
SIGNAL average_sum : signed(17 DOWNTO 0) := (OTHERS => '0');
SIGNAL average_result : signed(15 DOWNTO 0) := (OTHERS => '0');
...
-- within my process
average_sum <= average_sum + signed(my_signed_signal); -- loop 4 times
...
average_result <= average_sum(17 DOWNTO 2); -- how I finally get the result (div by 4)
I am aware that this should work for unsigned signals but I'm pretty sure it doesn't for signed ones because of the signed bit. Yet I don't really know what to change. Does anyone have an idea?
Yes, it works for signed types, too.

VHDL 8-bit multiplier, 3-bit input and 4-bit input, how to compensate for number of bits in output?

I have been working on a vhdl program that accepts 2 inputs, a 3-bit input and a 4-bit input. The 3-bit input represents "2 to the power of n", ie an input of 010(which is 2) would equal 2^2=4. An input of 110(which is 6) would yield 2^6 which is 64. This is to be multiplied by a 4-bit input from 0000 to 1111, and the answer stored as 8-bits. However, when I try to solve for this in VHDL, I keep getting the error "Expression error at midterm_q_one.vhd(34): expression has 12 elements, but must have 8 elements". I am new to VHDL, and searching online has yielded little result. I want a way for my output, in this case hex, to store the product of my 2 inputs as an 8 bit value but don't know how. Any help would be greatly appreciated and below is my code. Thanks!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity midterm_q_one is
port(en: in std_logic;
reset: in std_logic;
three_bit: in std_logic_vector(2 downto 0);
four_bit: in std_logic_vector(3 downto 0);
hex: out std_logic_vector(7 downto 0)
);
end midterm_q_one;
architecture arch of midterm_q_one is
signal temp : std_logic_vector(7 downto 0);
begin
process(en, reset, three_bit, four_bit)
begin
if(reset = '1') then
temp <= "00000000";--reset to decimal 0
elsif(en = '1') then
case three_bit is
when "000" => temp <= "00000001";--1
when "001" => temp <= "00000010";--2
when "010" => temp <= "00000100";--4
when "011" => temp <= "00001000";--8
when "100" => temp <= "00010000";--16
when "101" => temp <= "00100000";--32
when "110" => temp <= "01000000";--64
when "111" => temp <= "10000000";--128
end case;
end if;
hex <= temp * four_bit;
end process;
end arch;
Multiplication of the 8-bit temp with the 8-bit four_bit gives a 12-bit result, which is assigned to the 8-bit hex, thus the error message "expression has 12 elements, but must have 8 elements".
Suggestion: Get ridge of the non-standard (Synopsys) STD_LOGIC_ARITH and STD_LOGIC_UNSIGNED, and start using the standard numeric_std package.
With the numeric_std you can resize the result using:
library ieee;
use ieee.numeric_std.all;
...
hex <= std_logic_vector(resize(unsigned(temp) * unsigned(four_bit), hex'length));
I could see two ways to get rid of the error.
The simplest is:
architecture simple of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
begin
if reset = '1' then
hex <= (others => '0');
elsif en = '1' then
hex <= SHL("0000" & four_bit, three_bit);
end if;
end process;
end architecture;
This still requires some knowledge of what 8 bit's you want, or whether you want the value to clamp to x"FF" or whether you want the 8 bit best product:
architecture best_product of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
variable intermed: std_logic_vector (11 downto 0);
begin
if reset = '1' then
intermed := (others => '0');
elsif en = '1' then
intermed := SHL("0000" & four_bit, three_bit);
end if;
hex <= intermed(11 downto 4);
end process;
end architecture;
Clamping:
architecture saturate_clamp of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
variable intermed: std_logic_vector (11 downto 0);
begin
if reset = '1' then
intermed := (others => '0');
elsif en = '1' then
intermed := SHL("0000" & four_bit, three_bit);
end if;
if intermed(11) = '1' or intermed(10) = '1' or
intermed(9) = '1' or intermed(8) = '1' then
hex <= x"FF";
else
hex <= intermed(7 downto 0);
end if;
end process;
end architecture;
What are the 8 bits supposed to represent mathematically?

Adding Even Parity bit and 2 stop bits to a 8 bits std_logic_vector

Here is the code: In this the calculation for the parity bit is not done. Parity bit can be calculated using the for loop but is there any other short or better way to calculate the even parity bit in this context.
Is it somehow possible to use arrays instead of 8 TxDataReg std_logic_vector considering that after making arrays I wish to access bit by bit the array of 8 signals of 8 bits, bit by bit for sending the data in the uart_tx port?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Uart_tx is
Port (
tx_clk_in : in STD_LOGIC;
reset : in STD_LOGIC;
tx : out STD_LOGIC;
Rx_Data_in : in STD_LOGIC_VECTOR(63 downto 0)
);
end Uart_tx;
architecture Behavioral of Uart_tx is
signal Tx_Data : STD_LOGIC_VECTOR(63 downto 0) := "00000000";
signal DataByteArray1 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray2 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray3 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray4 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray5 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray6 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray7 : std_logic_vector(7 downto 0) := (others => "00000000");
signal DataByteArray8 : std_logic_vector(7 downto 0) := (others => "00000000");
signal TxDataReg1 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg2 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg3 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg4 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg5 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg6 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg7 : std_logic_vector(10 downto 0) := (others => "00000000");
signal TxDataReg8 : std_logic_vector(10 downto 0) := (others => "00000000");
signal count : unsigned(2 downto 0) := (others => '0');
signal one_bit : std_logic := '0';
begin
Tx_Data <= Rx_Data_in;
DataByteArray1 <= Rx_Data_in(7 downto 0);
DataByteArray2 <= Rx_Data_in(15 downto 8);
DataByteArray3 <= Rx_Data_in(23 downto 16);
DataByteArray4 <= Rx_Data_in(31 downto 24);
DataByteArray5 <= Rx_Data_in(39 downto 32);
DataByteArray6 <= Rx_Data_in(47 downto 40);
DataByteArray7 <= Rx_Data_in(55 downto 48);
DataByteArray8 <= Rx_Data_in(63 downto 56);
Process (tx_clk_in)
begin
-- Calculate the parity bit
for i in 0 to 7 loop
one_bit = DataByteArray1(i);
if one_bit = '1' then
count = count + 1;
end if;
end loop;
-- For all the registers,one even parity & two stop bits I am trying to add in the end
if count mod 2 = 0 then
TxDataReg1 <= DataByteArray1&'0'&'11'; -- I am not so sure that this works or not
count <= "000";
else
TxDataReg1 <= DataByteArray1&'1'&'11';
count <= "000";
end if;
-- Send the uart data from TxDataReg1,TxDataReg2 ...
-- etc.
end process;
end behavioral;
This UART would be much easier to understand if you created a State Machine. State Machines give your code an organized flow. The flow just makes more sense. In VHDL you can create enumerated states which means that you can give them names. I recommend this approach.
It's much harder to keep counters throughout your design to know exactly when to insert the parity bit or when to insert the 2 stop bits in your UART design. If you have a nice state machine it will make much more sense to you I believe. This is especially recommended for anyone new at FPGAs.
When you calculate your parity, just keep a running parity bit that gets an XOR with the outgoing serial data. Create a state to insert your parity bit at the correct time, then insert your two stop bits.
For an example of this, look at this UART VHDL Code
I would second the suggestion to reorganize this to use an FSM that works on just a byte at a time. Then you will have a general purpose async. TX entity that another controller can send bytes to as needed.
As to managing your data. It would be simpler if you created an array of byte arrays:
subtype byte is std_logic_Vector(7 downto 0);
type byte_array is array(natural range <>) of byte;
signal data_byte_array : byte_array(1 to 8);
signal byte_index : unsigned(2 downto 0);
...
-- Select the current byte
cur_byte <= data_byte_array(to_integer(byte_index));
The subtype isn't strictly necessary but it is a good habit to use for common data types to save you from littering your code with so many hard-coded array bounds.
For calculating parity you need to adopt the hardware mindset of implementing logic gates rather than the software approach of counting set bits. Parity calculation boils down to an XOR-reduce operation applied to all the bits in your vector. For even parity, you XOR all bits. For odd parity, you XOR all bits and invert the result. Because XOR is equivalent to a controlled inversion you can select the parity type by setting an initial state and performing one extra XOR to get the optional inversion based on your desire for odd or even.
-- Any VHDL:
variable parity : std_logic;
parity := '0'; -- Set to '1' to get odd parity
for i in cur_byte'range loop
parity := parity xor cur_byte(i);
end loop;
-- VHDL-2002
use ieee.reduce_pack.xor_reduce;
parity := xor_reduce(cur_byte);
-- VHDL-2008
parity := xor cur_byte;
In synthesis these approaches all boil down to the same logic so any of them is fine for all practical purposes. This is an explicitly parallel operation and you don't have to step through the byte bitwise with the unneeded overhead of a counter.
You have committed a cardinal sin of mixing the non-standard Synopsys libraries std_logic_unsigned, _signed, and _arith with the true standard numeric library numeric_std. Never mix them in the same file and, better yet, never use the Synopsys libraries at all. They are a historical aberration best forgotten.

How to convert 8 bits to 16 bits in VHDL?

I have an input signal from ADC convertor that is 8 bits (std_logic_vector(7 downto 0)). I have to convert them to a 16 bits signal (std_logic_vector(15 downto 0)) for 16 bits signal processing to the 16 bits system.
If the 8 bit value is interpreted as signed (2's complement), then the general and standard VHDL conversion method is to use the IEEE numeric_std library:
library ieee;
use ieee.numeric_std.all;
architecture sim of tb is
signal slv_8 : std_logic_vector( 8 - 1 downto 0);
signal slv_16 : std_logic_vector(16 - 1 downto 0);
begin
slv_16 <= std_logic_vector(resize(signed(slv_8), slv_16'length));
end architecture;
So first the std_logic_vector is converted to a signed value, then the resize is applied, which will sign extend the signed value, and the result is finally converted back to std_logic_vector.
The conversion is rather lengthy, but has the advantage that it is general and works even if the target length is changed later on.
The attribute 'length simply returns the length of the slv_16 std_logic_vector, thus 16.
For unsigned representation instead of signed, it can be done using unsigned instead of signed, thus with this code:
slv_16 <= std_logic_vector(resize(unsigned(slv_8), slv_16'length));
architecture RTL of test is
signal s8: std_logic_vector(7 downto 0);
signal s16: std_logic_vector(15 downto 0);
begin
s16 <= X"00" & s8;
end;
This handles the conversion without having to edit the widths of the zeroes if either std_logic_vector changes:
architecture RTL of test is
signal s8: std_logic_vector(7 downto 0);
signal s16: std_logic_vector(15 downto 0) := (others => '0');
begin
s16(s8'range) <= s8;
end;
For completeness, yet another way which is occasionally useful:
-- Clear all the slv_16 bits first and then copy in the bits you need.
process (slv_8)
begin
slv_16 <= (others => '0');
slv_16(7 downto 0) <= slv_8;
end process;
I've not had to do this for vectors that I can recall, but I have had need of this under more complex circumstances: copying just a few relevant signals into a bigger, more complex, record was one time.
With the newly released VHDL-2019 standard you can do
larger_vec <= extend(shorter_vec);
where extend is a function defined as follows
function extend(vec : std_logic_vector) return target_vec of std_logic_vector is
variable result : std_logic_vector(target_vec'length - 1 downto 0) := (others => '0');
begin
assert vec'length <= target_vec'length report "Cannot extend to shorter vector";
result(vec'length - 1 downto 0) := vec;
return result;
end function;
Tool support is still a bit limited but at least one simulator supports this (Riviera-PRO).

How to declare an output with multiple zeros in VHDL

Hello i am trying to find a way to replace this command: Bus_S <= "0000000000000000000000000000000" & Ne; with something more convenient. Counting zeros one by one is not very sophisticated. The program is about an SLT unit for an ALU in mips. The SLT gets only 1 bit(MSB of an ADDSU32) and has an output of 32 bits all zeros but the first bit that depends on the Ne=MSB of ADDSU32. (plz ignore ALUop for the time being)
entity SLT_32x is
Port ( Ne : in STD_LOGIC;
ALUop : in STD_LOGIC_VECTOR (1 downto 0);
Bus_S : out STD_LOGIC_VECTOR (31 downto 0));
end SLT_32x;
architecture Behavioral of SLT_32x is
begin
Bus_S <= "0000000000000000000000000000000" & Ne;
end Behavioral;
Is there a way to use (30 downto 0)='0' or something like that? Thanks.
Try this: bus_S <= (0 => Ne, others => '0')
It means: set bit 0 to Ne, and set the other bits to '0'.
alternative to the given answers:
architecture Behavioral of SLT_32x is
begin
Bus_S <= (others => '0');
Bus_S(0) <= ne;
end Behavioral;
Always the last assignment in a combinatoric process is taken into account. This makes very readable code when having a default assignment for most of the cases and afterwards adding the special cases, i.e. feeding a wide bus (defined as record) through a hierarchical block and just modifying some of the signals.

Resources