Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16596 Discussions

Adding 2 32-bit numbers and storing the result in a 33 bit register

Altera_Forum
Honored Contributor II
3,846 Views

Hello, 

I need to add two 32-bit unsigned numbers and need to store in a 33 bit register in VHDL. Is it possible to do so. If so, then please help me to do so. Thanks in advance
0 Kudos
19 Replies
Altera_Forum
Honored Contributor II
2,550 Views

 

--- Quote Start ---  

Hello, 

I need to add two 32-bit unsigned numbers and need to store in a 33 bit register in VHDL. Is it possible to do so. If so, then please help me to do so. Thanks in advance 

--- Quote End ---  

 

try this: 

 

result33bits <= "0"&dataA + dataB; -- assuming all unsigned
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

 

--- Quote Start ---  

try this: 

 

result33bits <= "0"&dataA + dataB; -- assuming all unsigned 

--- Quote End ---  

 

 

 

Thanks, I got the output. I have another doubt. I written the testbench code such that it performs 32 bit addition and stores in a 33 bit register. I am getting these errors in the next clock cycle (Only for 1 time) 

" Output is not set to default value when enable_i is 0" after I make reset to 0 and "Wrong output" after I make enable to 1. I know that this is because of the clocked process and that I need to define the values of new_mod_s and old_fcw_s whenever the clock is changed, but I don't know where to do these changes. Help me to solve this problem. Thanks in advance. 

 

The testbench is as follows: 

p_clock_gen :process begin clk_128meg_i <= '0'; wait for clk_128meg_i_period/2; clk_128meg_i <= '1'; wait for clk_128meg_i_period/2; end process; --stimulus p_stim: process begin wait for 10 ns; reset_n_i <= '1'; wait for clk_128meg_i_period; enable_i <= '1'; fcw_i <= "00000000000000000000000000000000"; mod_i <= "000000000000000000000000"; wait for 50 ns; fcw_i <= "11111001011110010001000101111111"; -- 4185461119 mod_i <= "110100001101110111010000"; -- 13688272 wait for 50 ns; fcw_i <= "10101011010101010101110101010111"; -- 2874498391 mod_i <= "000101110111011101101011"; -- 1537899 wait for 50 ns; fcw_i <= "11001011101101101110101011011101"; -- 3417762525 mod_i <= "000000100010110110110110"; -- 142774 wait for 50 ns; fcw_i <= "00101010101010101011010100101001"; -- 715830569 mod_i <= "101010101011010101010101"; -- 11187541 wait for 50 ns; fcw_i <= "11111111111111111111111111111111"; -- 4294967295 mod_i <= "111111111111111111111111"; -- 16777215 wait for 10 ms; reset_n_i <= '0'; wait for 1 ms; reset_n_i <= '1'; wait for 1 ms; enable_i <= '0'; wait for 1 ms; enable_i <= '1'; wait for 1 ms; assert false report " End of the simulation" severity Failure; end process; new_mod_s <= std_logic_vector("000000" & mod_i & "000"); old_fcw_s <= std_logic_vector("0" & fcw_i); delay_rst_s <= reset_n_i after 1 ns; p_fcw_chk: process(delay_rst_s, clk_128meg_i) begin if (delay_rst_s = '0') then assert fcw_mod_o = "000000000000000000000000000000000" report "Output is not set to default value when reset_n_i is 0" severity error; elsif (clk_128meg_i'event and clk_128meg_i = '0') then if (enable_i = '1') then assert fcw_mod_o = std_logic_vector(unsigned(old_fcw_s) + unsigned(new_mod_s)) report "Wrong output" severity error; else assert fcw_mod_o = "000000000000000000000000000000000" report "Output is not set to default value when enable_i is 0" severity error; end if; end if; end process;
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

Sory I don't get it. Are you trying to check your design or the testbench. Where is the design?

0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

the design code is here: 

entity add1 is port (reset_n_i : in std_logic; -- global reset clk_128meg_i : in std_logic; -- 128MHz system clock enable_i : in std_logic; -- global enable fcw_i : in std_logic_vector(31 downto 0); -- fractional number with 4 integer bits from MSB and 28 fractional bits (32 bit width) mod_i : in std_logic_vector(23 downto 0); -- 24 bit fractional number fcw_mod_o : out std_logic_vector(32 downto 0) -- fcw_i+(5 zeros & mod_i & 3 zeros) ); end add1; architecture rtl of add1 is signal temp_s : std_logic_vector(32 downto 0); -- Register to store the concatenated mod_i value signal mod_s : std_logic_vector(32 downto 0); -- Register to store the added output (fcw_i+temp_s) signal fcw_s : std_logic_vector(32 downto 0); -- Register to store the added output (fcw_i) begin p_add1 : process( reset_n_i, clk_128meg_i) begin if (reset_n_i = '0') then mod_s <= (others => '0'); elsif (clk_128meg_i'event and clk_128meg_i = '1') then if (enable_i = '1') then mod_s <= std_logic_vector(unsigned(fcw_s) + unsigned(temp_s)); -- Adding of fcw_i and temp_s results in mod_s else mod_s <= (others => '0'); end if; end if; end process; fcw_s <= std_logic_vector("0" & fcw_i); -- Five zeros are appended to the MSB of mod_i and three zeros are appended to the LSB of mod_i temp_s <= std_logic_vector("000000" & mod_i & "000"); -- Five zeros are appended to the MSB of mod_i and three zeros are appended to the LSB of mod_i fcw_mod_o <= std_logic_vector(mod_s); end rtl; Sorry for not uploading in the beginning
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

the design code is here: 

 

entity add1 is port (reset_n_i : in std_logic; -- global reset clk_128meg_i : in std_logic; -- 128MHz system clock enable_i : in std_logic; -- global enable fcw_i : in std_logic_vector(31 downto 0); -- fractional number with 4 integer bits from MSB and 28 fractional bits (32 bit width) mod_i : in std_logic_vector(23 downto 0); -- 24 bit fractional number fcw_mod_o : out std_logic_vector(32 downto 0) -- fcw_i+(5 zeros & mod_i & 3 zeros) ); end add1; architecture rtl of add1 is signal temp_s : std_logic_vector(32 downto 0); -- Register to store the concatenated mod_i value signal mod_s : std_logic_vector(32 downto 0); -- Register to store the added output (fcw_i+temp_s) signal fcw_s : std_logic_vector(32 downto 0); -- Register to store the added output (fcw_i) begin p_add1 : process( reset_n_i, clk_128meg_i) begin if (reset_n_i = '0') then mod_s <= (others => '0'); elsif (clk_128meg_i'event and clk_128meg_i = '1') then if (enable_i = '1') then mod_s <= std_logic_vector(unsigned(fcw_s) + unsigned(temp_s)); -- Adding of fcw_i and temp_s results in mod_s else mod_s <= (others => '0'); end if; end if; end process; fcw_s <= std_logic_vector("0" & fcw_i); -- Five zeros are appended to the MSB of mod_i and three zeros are appended to the LSB of mod_i temp_s <= std_logic_vector("000000" & mod_i & "000"); -- Five zeros are appended to the MSB of mod_i and three zeros are appended to the LSB of mod_i fcw_mod_o <= std_logic_vector(mod_s); end rtl; 

 

Sorry for not uploading in the beginning
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

so is your question why when enable is '0' the value of mod_s doesn't default zero?

0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

yes, exactly

0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

There is nothing wrong with adder logic. 

your problem possibly lies in the clock edge delay issues in your testbench (possibly delta delay issue). i.e. the eye tells you clock edge samples the change but in reality there is delta delay. 

make sure the signal transitions occur as intended relative to clock edge
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

Ok, got it. How to write some randomized inputs for this testbench a kind of a loop I mean

0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

 

--- Quote Start ---  

Ok, got it. How to write some randomized inputs for this testbench a kind of a loop I mean 

--- Quote End ---  

 

 

opion1 : manual successive assignments as you do but care is needed to check delay issues, use multiple of clock periods for delay. 

option2 : use clocked process to read from array or run prbs. The clocked process guarantees no delay issues relative to edge
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

Can you please give an example with a while loop doing so, because I don't need any variable to do this

0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

 

--- Quote Start ---  

Ok, got it. How to write some randomized inputs for this testbench a kind of a loop I mean 

--- Quote End ---  

 

 

This a prbs(25 downto 1): 

 

process(reset, clk) begin if(reset = '1')then shift_reg <= '0' & x"00F0F1"; elsif(rising_edge(clk))then shift_reg(1) <= shift_reg(25) xor shift_reg(22); shift_reg(25 downto 2) <= shift_reg(24 downto 1); end if; end process; 

 

then: 

 

assign fcw_i with some 32 bits (mix as you like) and assign mod_i 24 bits (choose your favourite bits) from shift_reg
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

 

--- Quote Start ---  

This a prbs(25 downto 1): 

 

process(reset, clk) begin if(reset = '1')then shift_reg <= '0' & x"00F0F1"; elsif(rising_edge(clk))then shift_reg(1) <= shift_reg(25) xor shift_reg(22); shift_reg(25 downto 2) <= shift_reg(24 downto 1); end if; end process; 

 

then: 

 

assign fcw_i with some 32 bits (mix as you like) and assign mod_i 24 bits (choose your favourite bits) from shift_reg 

--- Quote End ---  

 

 

Thats more of a logical approach. If you want a more programatical approach, VHDL has a built in random number generator: 

 

use ieee.math_real.all; -- for the uniform procedure; signal input : unsigned(7 downto 0); process variable seed1, seed2 : positive := 632165687; -- pick any positive value as a seed variable rand : real; begin wait until rising_edge(clk); uniform(seed1, seed2, rand); ip <= to_unsigned( integer((rand * real(2**input'length)), input'length); --makes random integer from 0 to 255 end process;
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

Thanks, 

I have written the test bench accordingly and it looks like this: 

 

p_rand_gen: process variable s1_v, s2_v: positive; variable rand_v: real; variable fcw_v : real := 40000.0; variable mod_v : real := 1600.0; begin wait for 25 ns; uniform(s1_v,s2_v,rand_v); rand_mod_s <= integer (rand_v*fcw_v); rand_fcw_s <= integer(rand_v *mod_v); wait for 10 ns; end process; --stimulus p_stim: process begin wait for 10 ns; reset_n_i <= '1'; wait for 15 ns; enable_i <= '1'; fcw_i <= std_logic_vector(to_unsigned(rand_fcw_s , 32)); mod_i <= std_logic_vector(to_unsigned(rand_mod_s, 24)); wait for 10 ms; reset_n_i <= '0'; wait for 1 ms; reset_n_i <= '1'; wait for 1 ms; enable_i <= '0'; wait for 1 ms; enable_i <= '1'; wait for 10 ms; assert false report " End of the simulation" severity Failure; end process; delay_rst_s <= reset_n_i after 1 ns; p_fcw_chk: process(delay_rst_s, clk_128meg_i) begin if (delay_rst_s = '0') then assert fcw_mod_o = "000000000000000000000000000000000" report "Output is not set to default value when reset_n_i is 0" severity error; elsif (clk_128meg_i'event and clk_128meg_i = '0') then if (enable_i = '1') then new_mod_s <= std_logic_vector("000000" & mod_i & "000"); old_fcw_s <= std_logic_vector("0" & fcw_i); assert fcw_mod_o = std_logic_vector(unsigned(old_fcw_s) + unsigned(new_mod_s)) report "Wrong output" severity error; else assert fcw_mod_o = "000000000000000000000000000000000" report "Output is not set to default value when enable_i is 0" severity error; end if; end if; end process;  

 

What I need to do is that, when the variables rand_mod_v and rand_fcw_v are updated, they should reflect the change at once in fcw_i and mod_i which I have written in the "stimuli: process", But its not getting updated. I don't know why. Thanks in advance
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

@Tricky, 

Thanks a lot. I have posted the problem previously. What I need to do is I need to update the values of fcw_i and mod_i after every 10 ns (ie, whenever the values of rand_mod_v and rand_fcw_v are updated). Please help me out to solve this problem. I am getting really frustrated
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

 

--- Quote Start ---  

 

What I need to do is that, when the variables rand_mod_v and rand_fcw_v are updated, they should reflect the change at once in fcw_i and mod_i which I have written in the "stimuli: process", But its not getting updated. I don't know why. Thanks in advance 

--- Quote End ---  

 

 

Thats because you have only assigned them once in the p_stim process, so they will have whatever value is on rand_fcw_s and rand_mod_s. Because both processes are meant to execute code at exactly the same time, they will take the initial values of the rand signals. 

 

You need a loop in your p_stim process to update the signals. why not just ditch the p_rand_gen process altogether and ut the random generation in the p_stim process?
0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

When I try to join the p_rand_num process along with p_stim process, then the values are not updated. Can you help me how to write a loop within the p_stim process to perform this operation. Please help me

0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

--stimulus p_stim: process variable s1_v, s2_v: positive; variable rand_v: real; variable fcw_v : real := 40000.0; -- Why are these variables and not constants? variable mod_v : real := 1600.0; -- Why are these variables and not constants? begin wait for 10 ns; reset_n_i <= '1'; wait for 15 ns; enable_i <= '1'; for i in 1 to N_INPUTS loop uniform(s1_v,s2_v,rand_v); rand_fcw_s <= integer(rand_v*mod_v); rand_mod_s <= integer(rand_v*fcw_v); fcw_i <= std_logic_vector(to_unsigned(rand_v*mod_v, 32)); mod_i <= std_logic_vector(to_unsigned(rand_v*fcw_v, 24)); wait until rising_edge(clk) -- much better to synchronise to the clock rather than waiting for a time period end loop; wait for 10 ms; reset_n_i <= '0'; wait for 1 ms; reset_n_i <= '1'; wait for 1 ms; enable_i <= '0'; wait for 1 ms; enable_i <= '1'; wait for 10 ms; assert false report " End of the simulation" severity Failure; end process;

0 Kudos
Altera_Forum
Honored Contributor II
2,550 Views

Thanks Tricky, 

That came out pretty much well. Bit relaxed right now.
0 Kudos
Reply