cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Observer
Observer
166 Views
Registered: ‎04-03-2020

Math operations on unsigned (adding)

I was using integers for my VHDL code but then I switched to unsigned because of the feedback I got here. In order to make sure I am doing the right thing, I tried to produce a ramp and send it to my MATLAB plotting code. I wrote the VHDL code in a component, here is the code I have inside the component:

library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;

entity SinWGen is
    Port (
    spi_adc_cs_b    : in  std_logic;
    sin             : out unsigned (15 downto 0);
    cos             : out unsigned (15 downto 0);
    state_param     : in integer range 0 to 3);
end SinWGen;

architecture Behavioral of SinWGen is

begin

    WaveGen: process(spi_adc_cs_b)
    
    variable cnt    : unsigned (15 downto 0) := (others => '0');
    variable tst    : unsigned (15 downto 0) := (12 => '1', others => '0');
    
    begin
    
    if(rising_edge(spi_adc_cs_b)) then
        if(state_param = 1) then
            if(cnt < 4000) then
                sin <= cnt;
                cnt:= cnt + 1000;
            else
                sin <= (others => '0');
                cnt := (others => '0');
            end if;
        end if;
    end if;
    
    end process WaveGen;

end Behavioral;

This is the section that I am concerned with:

     if(rising_edge(spi_adc_cs_b)) then
        if(state_param = 1) then
            if(cnt < 4000) then
                sin <= cnt;
                cnt:= cnt + 1000;
            else
                sin <= (others => '0');
                cnt := (others => '0');
            end if;
        end if;
    end if;

I expect the output "sin" to be a ramp with 1000 steps which goes to 4000 and then comes back to zero. It goes exactly opposit, starts from 4000, goes down to zero in 1000 steps!

I changed the 4000 and 1000 to unsigned (i.e. "BinaryData") and re-ran the code but the results are the same. So,

 

- Is this how I should be adding unsigned to another number?

- Is it ok if I use integers for these situations (because they are more straightforward) or do I have to convert my numbers to unsigned?

Thank you in advance for your help.

 

 

 

Tags (2)
0 Kudos
5 Replies
Highlighted
162 Views
Registered: ‎06-21-2017

Re: Math operations on unsigned (adding)

Make cnt a signal instead of a variable. 

0 Kudos
Highlighted
Scholar
Scholar
142 Views
Registered: ‎08-01-2012

Re: Math operations on unsigned (adding)

@bruce_karaffa 

That will make little difference here, as the assignment to cnt is done after the assigned of sin <= cnt; So the cnt will be a register as will sin. The code shows cnt incrementing in steps of 1000 up to 4000

@Mason1 

Why are you using the chip select signal as a clock?

0 Kudos
Highlighted
Observer
Observer
134 Views
Registered: ‎04-03-2020

Re: Math operations on unsigned (adding)

Long story short: I get a defined number of data and send it to an MCU, I am producing the CS! and SCK locally and use CS! as my reference here because it can easily count the number of samples that I get. In other words, the SPI is my core operation here and I prefer to use its clock for side operations as well. Let me know if this is the answer you were expecting. Thanks for your help. 

0 Kudos
Highlighted
Observer
Observer
61 Views
Registered: ‎04-03-2020

Re: Math operations on unsigned (adding)

I changed the code and converted the variable to signal, I also copied the code into a top module, here is how it looks like now:

library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;

entity Top is
    Port ( clk : in STD_LOGIC);
end Top;

architecture Behavioral of Top is

signal cnt      : unsigned (15 downto 0) := (others => '0');
signal sin      : unsigned (15 downto 0);

begin

    WaveGen: process(clk)
    
--    variable cnt    : unsigned (15 downto 0) := (others => '0');
    variable tst    : unsigned (15 downto 0) := (12 => '1', others => '0');
    
    begin
    
    if(rising_edge(clk)) then

            if(cnt < "0000111110100000") then
                sin <= cnt;
                cnt<= cnt + "0000001111101000";
            else
--                sin <= (others => '0');
                cnt <= (others => '0');
            end if;
    end if;
    
    end process WaveGen;

end Behavioral;

Then, I simulated the code. Here are the simulation results:

wave.PNG

 

Which seems correct. But when I run the code and see the results in MATLAB, I see the following (normalized to a 3.3 V reference):

untitled.jpg

 

I really think my communication code does not have the capability of flipping the data before sending them. It is quite strange that my staircase has a negative ramp while the simulation shows the opposite. Also,

"0000111110100000" = 4000

"0000001111101000" = 1000

 

0 Kudos
Highlighted
38 Views
Registered: ‎01-22-2015

Re: Math operations on unsigned (adding)

@Mason1 

Some thoughts:

  1. Your latest VHDL works!  That is, cnt will increment as 0, 1000, 2000, 3000, 4000, 0, 1000, 2000, ....
  2. When working with VHDL unsigned, we tend to write constants using hex notation rather than binary notation - just because it is easier and less prone to error.  For example with unsigned(15 downto 0), you have dec(1000) = "0000001111101000" = x"03E8".  Many calculators (eg. the one found in MS WIN10) have a "Programmer" setting which makes it easy to convert from decimal to hex notation.
  3. If Vivado behavioral simulation shows that our VHDL is working then we usually say GREAT and move on.  
  4. There is nothing wrong with using MATLAB to further verify things - but  (as you say) there is a communication interface to worry about and somehow MATLAB is converting your unsigned numbers to an ADC voltage?  In this case, I think your use of MATLAB is not helping with your FPGA work.

Cheers,
Mark