VHDL code to find square root of number? - vhdl

Is there is any in built function or any library that can be included in the design to find square root of a number?

Restoring square root algorithm is easy to implement on fpga, wikipedia has an example.
FPGA vendors should have cores available, it hides inside the general purpose CORDIC core on Xilinx. They also have square root cores for floating points, if that's what you need.

For non-synthesizable (simulation/test-bench only) operation, square root for real can be done with:
y := math_real.sqrt(x)
For synthesizable operation, see answer from Jonathan Drolet.

This one worked for me.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_unsigned.ALL;
entity squart is port(
clock : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(3 downto 0)); end squart;
architecture behaviour of squart is
signal part_done : std_logic := '0';
signal part_count : integer := 3;
signal result : std_logic_vector(4 downto 0) := "00000";
signal partialq : std_logic_vector(5 downto 0) := "000000";
begin
part_done_1: process(clock, data_in, part_done)
begin
if(clock'event and clock='1')then
if(part_done='0')then
if(part_count>=0)then
partialq(1 downto 0) <= data_in((part_count*2)+ 1 downto part_count*2);
part_done <= '1'; else
data_out <= result(3 downto 0);
end if;
part_count <= part_count - 1;
elsif(part_done='1')then
if((result(3 downto 0) & "01") <= partialq)then
result <= result(3 downto 0) & '1';
partialq(5 downto 2) <= partialq(3 downto 0) - (result(1 downto 0)&"01");
else
result <= result(3 downto 0) & '0';
partialq(5 downto 2) <= partialq(3 downto 0);
end if;
part_done <= '0';
end if;
end if;
end process;
end behaviour;

Check this one:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SQRT is
Generic ( b : natural range 4 to 32 := 16 );
Port ( value : in STD_LOGIC_VECTOR (15 downto 0);
result : out STD_LOGIC_VECTOR (7 downto 0));
end SQRT;
architecture Behave of SQRT is
begin
process (value)
variable vop : unsigned(b-1 downto 0);
variable vres : unsigned(b-1 downto 0);
variable vone : unsigned(b-1 downto 0);
begin
vone := to_unsigned(2**(b-2),b);
vop := unsigned(value);
vres := (others=>'0');
while (vone /= 0) loop
if (vop >= vres+vone) then
vop := vop - (vres+vone);
vres := vres/2 + vone;
else
vres := vres/2;
end if;
vone := vone/4;
end loop;
result <= std_logic_vector(vres(result'range));
end process;
end;

Related

Can't normally see result in wave (Modesim)

I have code designed for Vivid software. How I can translate this code into ModelSIM? In vivado, I should get the following values, but in modelsim I get completely different ones.
This is noise generator. Successful in adding pseudorandom noise sequence to our sine wave, but now we are trying to add Gaussian noise. The code and the simulation results for ADDITION OF PSEUDORANDOM NOISE SEQUENCE TO SINE WAVE IS GIVEN BELOW:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; --try to use this library as much as possible.
entity sine_wave is
generic ( width : integer := 4 );
port (clk :in std_logic;
random_num : out std_logic_vector (width-1 downto 0);
data_out : out STD_LOGIC_VECTOR(7 downto 0)
);
end sine_wave;
architecture Behavioral of sine_wave is
signal data_out1,rand_temp1,noisy_signal : integer;
signal noisy_signal1 : STD_LOGIC_VECTOR(7 downto 0);
signal i : integer range 0 to 29:=0;
--type memory_type is array (0 to 29) of integer;
type memory_type is array (0 to 29) of std_logic_vector(7 downto 0);
--ROM for storing the sine values generated by MATLAB.
signal sine : memory_type := ("01001101","01011101","01101100","01111010","10000111","10010000","10010111","10011010","10011010");
--hi
begin
process(clk)
variable rand_temp : std_logic_vector(width-1 downto 0):=(width-1 => '1',others => '0');
variable temp : std_logic := '0';
begin
--to check the rising edge of the clock signal
if(rising_edge(clk)) then
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;
--data_out <= sine(i);
i <= i+ 1;
if(i = 29) then
i <= 0;
end if;
end if;
data_out <= sine(i);
data_out1<=to_integer(unsigned(sine(i)));
random_num <= rand_temp;
rand_temp1<=to_integer(unsigned(rand_temp));
noisy_signal<=data_out1+rand_temp1;
noisy_signal1<= std_logic_vector(to_signed(noisy_signal,8));
end process;
end Behavioral;
Vivado
ModelSIM

Create "Init" and "End" SIGNAL for module in VHDL

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity struture_test is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
Init : in STD_LOGIC;
i_ia : in STD_LOGIC_VECTOR (11 downto 0);
i_ib : in STD_LOGIC_VECTOR (11 downto 0);
end_s : out std_logic;
result : out STD_LOGIC_VECTOR (11 downto 0));
end struture_test;
architecture Behavioral of struture_test is
signal en_sn : std_logic := '0';
begin
PROCESS (clk,rst)
variable acc : signed (23 downto 0) ;
variable x : signed (35 downto 0) ;
begin
if (rst = '0') then
result <= (others => '0');
end_s <= '0';
elsif (rising_edge (clk)) then
if ((Init) = '1') then
acc := signed (i_ia)*signed (i_ib);
x := acc * signed (i_ia);
result <= std_logic_vector (x(23 downto 12));
end_s <= '1';
else
end_s <= '0';
end if;
end if;
end process;
end Behavioral;
Hi everyone
I have a project which includes some blocks. The blocks link each other through Init or End Signal. It means that The End signal of one Block is connected to Init signal of the following block.
I'm confused about that Does the above code make a good Init and a End signal ?
If I change my code and convert it into Pipelined structure to operate with the higher frequency clock. The variables convert into the signals
PROCESS (clk,rst)
signal acc : signed (23 downto 0) ;
signal x : signed (35 downto 0) ;
begin
if (rst = '0') then
result <= (others => '0');
end_s <= '0';
elsif (rising_edge (clk)) then
if ((Init) = '1') then
acc <= signed (i_ia)*signed (i_ib);
x <= acc * signed (i_ia);
result <= std_logic_vector (x(23 downto 12));
end_s <= '1';
else
end_s <= '0';
end if;
end if;
end process;
How to create Init and End signal in this case? The block illustrates in the picture
The idea is good, but the code is wrong. In addition it has some bad coding smells.
Basic rules:
Do not use asynchronous resets.
You can not declare signals in processes. Process allow variable declarations; architectures allow signal declarations.
Each signal assignment in a clock process creates a flip-flop / delay of one clock cycle. So it's 3 clock cycles delay in total, but you end signal is only delayed by one cycle.
Do not enable pipelined operations. Use a delayed chain of valid bits.
Do not reset pipeline results, because underlying hardware resources like DSP (multiplication) units do not support resets.
Changed code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity struture_test is
port (
clk : in std_logic;
rst : in std_logic;
Init : in std_logic;
i_ia : in std_logic_vector(11 downto 0);
i_ib : in std_logic_vector(11 downto 0);
end_s : out std_logic;
result : out std_logic_vector(11 downto 0) := (others => '0');
);
end entity;
architecture rtl of struture_test is
signal ValidChain : std_logic_value(2 downto 0) := (others => '0');
signal ia_delayed : signed(i_ia'range) := (others => '0');
signal acc : signed(23 downto 0) := (others => '0');
signal x : signed(35 downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
ValidChain <= ValidChain(ValidChain'high - 1 downto ValidChain'low) & Init;
acc <= signed(i_ia) * signed(i_ib);
ia_delayed <= signed(i_ia);
x <= acc * ia_delayed;
result <= std_logic_vector(x(23 downto 12));
end if;
end process;
end_s <= ValidChain(ValidChain'high);
end architecture;
Please note: Signal i_ia used in the 2nd multiplication needs to be delayed by one cycle, otherwise you would mix ia values from different pipeline cycles.

Issue with using component and forloop in VHDL

I am trying to create a component for division in VHDL, below is my code. I dont know where i am going wrong. My logic is:
At every step,
• shift divisor right and compare it with current dividend
• if divisor is larger, shift 0 as the next bit of the quotient
• if divisor is smaller, subtract to get new dividend and shift 1
as the next bit of the quotient.
I have used '-' sign here but in actual i have to use gates so either i have to use my subtraction component or just create a subtractor here.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
ENTITY divprog IS
PORT(
a: IN std_logic_vector(3 downto 0);
b: IN std_logic_vector(3 downto 0);
err: OUT std_logic;
reslow: OUT std_logic_vector(3 downto 0);
reshigh: OUT std_logic_vector(3 downto 0));
END divprog;
architecture behaviour of divprog is
signal ax,bx,bsub,res :std_logic_vector(7 downto 0) := (others => '0');
signal quo: std_logic_vector(3 downto 0) := (others => '0');
signal intcarry: std_logic_vector(8 downto 0):= (others => '0');
BEGIN
--sub1: subtractor PORT MAP(aa,bb,x,ss);
Process is
variable i : POSITIVE := 1;
BEGIN
ax <= "0000" & a;
bx <= b & "0000";
if(b > "0000") then
while (i <=3) loop
bx <= '0'&bx(7 downto 1);
IF (ax < bx) then
quo <= quo(2 downto 0)& '0';
--bx <= '0'&bx(7 downto 1);
res <=ax;
elsif(ax >= bx) then
res <= ax - bx;
quo <=quo(2 downto 0)& '1';
end if;
i := i + 1;
ax <= res;
end loop;
reshigh <= quo;
reslow <= res(3 downto 0);
end IF;
wait for 100 ns;
END PROCESS;
end behaviour;
Can please someone help me with this?
Thanks
The functional problem is related to variable i. It gets stuck at 4 after the first 100ns. It should be set to 1 between BEGIN and END PROCESS.

How to fill a vector bit by bit

I have a 12 bits vector called RDIBits and a in std_logic called InUartToUart. My question is: every time the clock goes to '1', i receive a bit in InUartToUart, and i want to concat all the 12 bits that i will receive in the RDIBits vector. Basically, its a serial communication, thats why i receive 1 bit each time. Is there any simple way to do this? Something similar to RDIBits += InUartToUart in JAVA.
I would code this slightly differently. Maybe consider this.
Sorry about the formatting, Im new to this site. I have also shown how you can initialise the variable.
signal RDIBits : std_logic_vector(11 downto 0) := (Others => '0');
...
process(clk)
begin
if ( rising_edge(clk) ) then
RDIBits(11 downto 1) <= RDIBits(10 downto 0);
RDIBits(0) <= InUartToUart;
end if;
end process;
I added some more things, like the entity, the IOs and a counter for the output register.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY my_uart IS
PORT(
clk : IN std_logic; -- system clock
rst : IN std_logic; -- reset high active
---------------------------------------------
InUartToUart : IN std_logic;
DataOut : OUT std_logic_vector(11 downto 0)
);
END ENTITY;
ARCHITECTURE struct OF my_uart IS
signal RDIBits : std_logic_vector(11 downto 0);
signal counter : integer range 0 to 12;
begin
calc_proc: process(clk, rst)
begin
if (rst = '1') then
RDIBits <= (others => '0');
counter <= 0;
elsif ( rising_edge(clk) ) then
if (counter < 12) then
RDIBits <= RDIBits(10 downto 0) & InUartToUart;
counter <= counter + 1;
elsif (counter = 12) then
DataOut <= RDIBits;
counter <= 0;
end if;
end if;
end process;
END STRUCT;
This is a typical shift register application. For example:
signal RDIBits : std_logic_vector(11 downto 0);
...
process(clk)
begin
if ( rising_edge(clk) ) then
RDIBits <= RDIBits(10 downto 0) & InUartToUart;
end if;
end process;

VHDL code runs but timing diagram shows nothing

I am trying to implement a cache memory 16 * 37 in VHDL in DesignWorks 5. The code is given below.
The code runs but when i change values from IO panel or even simulate anyway, the timing diagram shows nothing and basically the code is not running for some reason. Any suggestions would be really helpful.
Code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity Cache is
port(cs, r, clr : in std_logic;
data : in std_logic_vector(31 downto 0);
addr : in std_logic_vector(7 downto 0);
cline : out std_logic_vector(31 downto 0);
ctag: out std_logic_vector(3 downto 0);
v : out std_logic);
end Cache;
architecture behav of Cache is
type RAM is array (0 to 15) of std_logic_vector(36 downto 0);
begin
process is
variable M : RAM;
variable locn : natural;
variable temp_val : std_logic_vector(36 downto 0);
variable cline_val : std_logic_vector(31 downto 0);
variable ctag_val : std_logic_vector(3 downto 0);
variable v_val : std_logic;
begin
if cs = '1' then
locn := to_integer(addr);
if r = '1' then
temp_val := M(locn);
cline_val := temp_val(31 downto 0);
ctag_val := temp_val(35 downto 32);
v_val := temp_val(36);
else
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
M(locn) := temp_val;
v_val := 'Z';
ctag_val:= "ZZZZ";
cline_val:= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
end if;
end if;
if clr ='1' then
locn := 0;
while(locn<16) loop
M(locn) := X"000000000" + "0";
locn:=locn+1;
end loop;
end if;
cline <= cline_val;
ctag <= ctag_val;
v <= v_val;
wait on cs;
end process;
end behav;
This line:
M(locn) := X"000000000" + "0";
appears incorrect.
M is your ram array type with an element length of 37. A 36 bit zero added to zero is still 36 bits (it doesn't look like you reached this statement, it would be a run time error).
To make a length 37 vector of '0' values use `(others => '0').
You can also use a for loop for the ram clear, you need to not use an index of 16, it's out of range, which tells us you didn't reach the clear either.
I think you ought to show us your stimulus otherwise your problems can't be reproduced.
Your missing data and addr as sensitivity elements (and ya, you case cs surrounds, but you want to build a hardware model here).
Switch to a sensitivity list (cs, data, addr).
locn is an unconstrained natural and should have a range matching the array type ram (0 to 15). Notice your while loop reaches 16. Really, use a for loop (shown below). The reason for constraining locn is to prevent a bound error when accessing ram(locn).
Note for converting addr to a natural (locn) you need to AND mask addr with a length four run of '1's to prevent a range error for normal ram operations.
The package numeric_std is an affectation, it's easier than passing a couple of command line options to ghdl (ieee=synopsys -fexplict) during analysis and elaboration.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cache is
port (
cs, r, clr: in std_logic;
data: in std_logic_vector(31 downto 0);
addr: in std_logic_vector(7 downto 0);
cline: out std_logic_vector(31 downto 0);
ctag: out std_logic_vector(3 downto 0);
v: out std_logic
);
end entity;
architecture behav of cache is
type ram is array (0 to 15) of std_logic_vector(36 downto 0);
begin
process (cs, data, addr)
variable m : ram;
variable locn : natural range (ram'range);
variable temp_val : std_logic_vector(36 downto 0);
variable cline_val : std_logic_vector(31 downto 0);
variable ctag_val : std_logic_vector(3 downto 0);
variable v_val : std_logic;
begin
if cs = '1' then
locn := to_integer(unsigned(addr and x"0F"));
if r = '1' then
temp_val := m(locn);
cline_val := temp_val(31 downto 0);
ctag_val := temp_val(35 downto 32);
v_val := temp_val(36);
else
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
m(locn) := temp_val;
v_val := 'Z';
ctag_val:= "ZZZZ";
cline_val:= (others => 'Z');
end if;
end if;
if clr ='1' then
for i in ram'range loop
m(i) := (others => '0');
end loop;
end if;
cline <= cline_val;
ctag <= ctag_val;
v <= v_val;
end process;
end architecture;
This code analyzes and elaborates, you could have an error somewhere I didn't mention, and bound (range) errors show up at run time in assignments (expressions can not care).
And one final bit:
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
can be expressed:
temp_val:= '1' & addr(3 downto 0) & data;
As well as:
locn := to_integer(addr);
expressed as:
locn := to_integer(addr(3 downto 0));
You can also create an AND mask with a length defined algorithmically from the ram'range should you set the ram size with a generic.
And without seeing your stimulus there are several places that could cause run time errors. Check your console output.

Resources