cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Observer
Observer
263 Views
Registered: ‎04-03-2020

Math operations on unsigned (adding)

Jump to solution

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
1 Solution

Accepted Solutions
Highlighted
135 Views
Registered: ‎01-22-2015

@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

View solution in original post

6 Replies
259 Views
Registered: ‎06-21-2017

Make cnt a signal instead of a variable. 

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

@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
231 Views
Registered: ‎04-03-2020

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
158 Views
Registered: ‎04-03-2020

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
136 Views
Registered: ‎01-22-2015

@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

View solution in original post

Highlighted
Observer
Observer
79 Views
Registered: ‎04-03-2020

As you said, I had a problem with communication.

I was skipping some samples and jumping to the 3rd next sample instead of the next:

Current sample: #3

Next Sample: #2 (should be #4 but it goes to #4, then #1, then #2)

This gave me a wrong illusion.

0 Kudos