Forum Discussion
Devide in VHLD
I want to implement this function : A<= B/x"A", when I compile, the Quartus put a notice: "/" used but didn't declare.
When I try with "*" (multiply) or "+" (add), it is ok. I don't know this error, Please help me. Thank you very much.37 Replies
- Altera_Forum
Honored Contributor
The output is not valid until CNT is 2 anyway, so until then all signals are rubbish.
- Altera_Forum
Honored Contributor
Dear FvM
I want to implement Multiplication command in VHDL. Because Modelsim does not support for LPM library. And when I use multiply command directly, the result's not true with the negative number. In this method, I multiply two positive number, and use sign<=A(15)xor B(15); to check the sign of A and B. If sign=0 => the result's positive. else the result's negative. When I simulate with the waveforms, it appear strange value. I did not understand it. Do you have other idea for this? - Altera_Forum
Honored Contributor
Alt first sight, the result_out waveform seems not to fit the above design (it may be still possible under specific conditions). result_out is a registered signal, clocked by the 100 MHz clock, but it changes shortly before the next rising edge, usually causing a setup violation for the following logic. Without knowing the previous states of all signals, and the timing constraints in effect, I can only guess about the reason for this behaviour.
I also don't understand the purpose of the strange method to do a signed multiplication. The ABS() function is by the way causing an overflow for the most negative number -32768 (0x8000), which hasn't a corresponding positive value. P.S.: I see, that a similar negation method has been used previously in the thread. It may be a workaround for algorithms, that aren't avaliable for negative numbers for some reason. But multiply is. - Altera_Forum
Honored Contributor
Dear Tricky and Daixiwen
Could you check this code for me? When I simulate by waveforms vector of Quartus, at Result_out, the final result is true but I have a lot of result Ex: (-30)x(-6) = 180 but I saw, they have 16, 148, 180. (I attached this waveforms in this message) I don't know this value. Thanks before.library IEEE; USE IEEE.std_logic_1164.all; USE IEEE.numeric_std.all; Entity Multvhdl is Port ( A,B : In Signed(15 downto 0); --A*B Result_out : Out Signed(31 downto 0); CLK : In std_logic); end Multvhdl; Architecture structural of Multvhdl is Signal Multiplicant,Multiplier : Signed(15 downto 0); Signal Result : Signed(31 downto 0); Signal CNT : unSigned(3 downto 0); Signal Sign : unSigned(1 downto 0); Begin Process(clk) Begin if clk='1' and clk'event then cnt<=cnt+"1"; sign<="0" & (A(15)xor B(15)); --Check sign of A and B if cnt="0000" then Multiplicant<= ABS (A); Multiplier<= ABS (B); elsif cnt="0001" then Result<=Multiplicant*Multiplier; elsif cnt="0010" then if sign = "00" then Result_out<=result; elsif sign = "01" then Result_out<= -result; end if; cnt<="0000"; end if; end if; end process; end structural; - Altera_Forum
Honored Contributor
--- Quote Start --- two methods: 1. result <= (not result) + 1; 2. (probably easiest) result <= -result; (this will probably result in the same hardware as above when synthesised). --- Quote End --- Oh. It's so easy but I don't find out. Thank Tricky very much. Thanks Daixiwen for your usefull information. - Altera_Forum
Honored Contributor
And if you need more information about how to represent negative numbers in binary, this page from wikipedia (http://en.wikipedia.org/wiki/two's_complement) should answer your questions.
- Altera_Forum
Honored Contributor
two methods:
1. result <= (not result) + 1; 2. (probably easiest) result <= -result; (this will probably result in the same hardware as above when synthesised). - Altera_Forum
Honored Contributor
--- Quote Start --- what you want to do is take the absolute of A and B, but also store the signedness of them and follow these rules: If A and B are the same (ie. both positive or both negative), then result is positive. If A and B are different, then the result is negative. At the moment, you only ever create a postive result because you only ever add 1. You need to stick the XOR of MSBs of A and B into a shift register and then negate the output when needed. --- Quote End --- Oh. Thank you very much. That's a good idea. I have more question: To display -5 => 11111011 -3 => 11111101 How to change from 5 (00000101_binary) > -5 (11111011_binary) - Altera_Forum
Honored Contributor
what you want to do is take the absolute of A and B, but also store the signedness of them and follow these rules:
If A and B are the same (ie. both positive or both negative), then result is positive. If A and B are different, then the result is negative. At the moment, you only ever create a postive result because you only ever add 1. You need to stick the XOR of MSBs of A and B into a shift register and then negate the output when needed. - Altera_Forum
Honored Contributor
--- Quote Start --- comment out std_logic_arith and std_logic_unsigned packages. Bring back numeric_std package. Then make remainder and divider signals signed types. You cannot assign a "signed" type to a std_logic_vector. --- Quote End --- Thanks tricky I have a big problem with this code. If A,B> 0, It's OK. But A or B < 0. the result not correct. Could you help me?library IEEE; USE IEEE.std_logic_1164.all; USE IEEE.numeric_std.all; Entity Devide is Port ( A,B : In Signed(7 downto 0); --A/B Quotients,Remainder_out : Out Signed(7 downto 0); CLK : In std_logic); end Devide; Architecture structural of Devide is Signal Remainder,Divider : Signed(7 downto 0); Signal Result : Signed(7 downto 0); Signal CNT : unSigned(3 downto 0); Begin Process(clk) Begin if clk='1' and clk'event then cnt<=cnt+"1"; if cnt="0000" then if B="00000000" then cnt<="0000"; else Remainder<= A;--ABS (signed(A)); --Remainder = ABS(A) Divider<= B;--ABS (signed(B)); -- Divider = ABS(B) end if; elsif cnt="0001" and Remainder >= Divider then Result<=Result+1; Remainder<=Remainder-Divider; elsif cnt="0010" and Remainder >= Divider then cnt<="0001"; elsif cnt="0011" then Quotients<=result; Remainder_out<=Remainder; elsif cnt="0100" then cnt<="0000"; result<="00000000"; end if; end if; end process; end structural;