discrete cosine transform using VHDL - vhdl

Am working on discrete cosine transform using VHDL. Am trying to convert the VHDL code from integer to standard logic vector. I applied some of the techniques i read online and from textbooks but it didn't work. Below is the code i tried converting.I would like the input length to be 8 bit and the output length to be 12bit.Thank you.
entity dct is
port (
Clk : in BIT;
Start : in BIT;
Din : in INTEGER;
Done : out BIT;
Dout : out INTEGER
);
end dct;
architecture behavioral of dct is
begin
process
type RF is array ( 0 to 7, 0 to 7 ) of INTEGER;
variable i, j, k : INTEGER;
variable InBlock : RF;
variable COSBlock : RF;
variable TempBlock : RF;
variable OutBlock : RF;
variable A, B, P, Sum : INTEGER;
begin
Here is the one i tried after reading some books and i keep getting errors.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity dct is
port (
Clk : in std_logic;
Start : in std_logic;
Din_temp: in INTEGER;
temp := conv_std_logic_vector(Din_temp, 8);
Done : out std_logic;
Dout_temp: out INTEGER;
temp := conv_std_logic_vector(Dout_temp, 9));
end dct;
architecture behavioral of dct is
begin
process
type RF is matrix( 0 to 7, 0 to 7 ) of ;
variable i, j, k : std_logic_vector(7 downto 0);
variable InBlock : RF;
variable COSBlock : RF;
variable TempBlock : RF;
variable OutBlock : RF;
variable A, B, P, Sum : std_logic_vector(7 downto 0);
begin

seems that you combined the entity declaration with the signal assignement; this doesn't work like this! keep the entity as it was and use the type conversion functions inside your architecture. the example below shows this for Din and Dout:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity dct is
port (
Clk : in BIT;
Start : in BIT;
Din : in INTEGER;
Done : out BIT;
Dout : out INTEGER
);
end dct;
architecture behavioral of dct is
signal temp_din: std_logic_vector(7 downto 0);
signal temp_dout: std_logic_vector(11 downto 0);
begin
temp_din<=std_logic_Vector(to_unsigned(Din,8));
Dout<=to_integer(unsigned(temp_dout));
...
of course, you can also use std_logic_vector directly in your entity:
entity dct is
port (
Clk : in BIT;
Start : in BIT;
Din : in std_logic_Vector(7 downto 0);
Done : out BIT;
Dout : out std_logic_vector(11 downto 0)
);
end dct;

Integers are perfectly synthesisable and work just fine as ports, so if the module you have is working satisfactorily, and synthesise correctly, leave it well alone.
It is good practice to use ranged integers : for example, if Din, Dout represent values in the range 0 to 255, create either a new integer type or a subtype for them :
type Int_8 is new Integer range 0 to 255; -- or
subtype Int_8 is Integer range 0 to 255;
(The difference is that subtypes can be freely mixed with other Integers, but accidentally mixing the new type with integer will be flagged by the compiler as an error).
The benefit of this is that synthesis won't try to create 32-bit math units where only 8 (or 3 or 19) bits is needed. Normally it does, then trims the excess bits later so it doesn't cost any more gates, it just floods the report files with "trimming redundant logic" messages...
However I am guessing the problem you have is interfacing this core with other parts of a design, implemented in a less enlightened fashion, which have std_logic_vector ports.
Then you can implement a wrapper to adapt this DCT core to a std_logic_vector environment.
I have used different techniques for different port signals : conversions in the port maps are neater, but some tools have problems (bugs) handling them. So I have used internal signals as adapters for Start and Dout, to show how you can work around such problems.
In reality, pick one or the other!
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity std_lv_dct is
port (
Clk : in std_logic;
Start : in std_logic;
Din : in std_logic_vector(7 downto 0);
Done : out std_logic;
Dout : out std_logic_vector(11 downto 0);
);
end std_lv_dct;
architecture wrapper of std_lv_dct is
Dout_int : integer range 0 to 4095;
Start_int : bit;
begin
-- internal signals as type adapters
Dout <= std_logic_vector(to_unsigned(Dout_int),11);
Start_int <= to_bit(Start);
-- direct entity instantiation for the real core
Transform : entity work.dct
port map(
Clk => to_bit(Clk),
Start => Start_int,
Din => to_integer(unsigned(Din)),
std_logic(Done) => Done,
Dout => Dout_int
);
end architecture wrapper;

Related

How can i use generic array type with modelsim?

It's my first question here, I really hope you can help me
Edit 03 December 2019 :
We resolved our problem with the declaration type, but now, we have other problem
So, when I tried to run my testbench for the simulation on modelsim, we got these errors.
# Conv_rev3_run_msim_rtl_vhdl.do
# invalid command name "Conv_rev3_run_msim_rtl_vhdl.do"
Here our package for the declaration of type
-- synthesis VHDL_INPUT_VERSION VHDL_2008
library ieee;
use ieee.std_logic_1164.all;
package conv_p is
type slv_array_t is array (natural range <>) of std_logic_vector;
end package;
The entity of the main files
entity Conv_rev3 is
generic(
LEN : natural := 8; -- Bits in each input
NUM : natural := 4); -- Number of inputs
port(
clk : in std_logic;
D : in conv_p.slv_array_t(0 to NUM - 1)( LEN - 1 downto 0);
W : in conv_p.slv_array_t(0 to NUM - 1)( LEN - 1 downto 0);
z_o : out std_logic_vector(LEN*2 - 1 downto 0));
end entity;
Here a sample of our testbench :
LIBRARY IEEE;
USE ieee.std_logic_1164.all;
USE work.conv_p;
ENTITY Conv_rev3_vhd_tst IS
END Conv_rev3_vhd_tst;
ARCHITECTURE Conv_rev3_arch OF Conv_rev3_vhd_tst IS
-- constants
-- signals
SIGNAL clk : STD_LOGIC;
SIGNAL D : conv_p.slv_array_t(0 to 3)(7 downto 0);
SIGNAL W : conv_p.slv_array_t(0 to 3)(7 downto 0);
SIGNAL z_o : STD_LOGIC_VECTOR(15 DOWNTO 0);
COMPONENT Conv_rev3
PORT (
clk : IN STD_LOGIC;
D : IN conv_p.slv_array_t(0 to 3)(7 downto 0);
W : IN conv_p.slv_array_t(0 to 3)(7 downto 0);
z_o : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
);
END COMPONENT;
Best Regards
In your first problem, it is highly probable that the entity name that you have specified in your code is wrong and that is why it is unable to find that entity and shows that error. And thus it goes without saying that if it hasn't even found the entity, then it won't be able to compile it.
Now I don't think that there is need to answer the second question because there must be some error in it.

VHDL typecast signed to std_logic_vector

I am looking at this example and below answer which is a nice solution to produce two's complement:
library ieee;
use ieee.numeric_std.all;
entity twoscomplement is
generic
(
Nbits : positive := 8
);
port
(
A : in unsigned (Nbits-1 downto 0);
Y : out signed (Nbits downto 0)
);
end entity twoscomplement;
architecture a1 of twoscomplement is
begin
Y <= -signed(resize(A, Y'length));
end architecture;
I want to use the said example to have two's complement and then make a "16-bit subtractor". The code will look like the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity subtractor_16bit is
Port ( a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end subtractor_16bit;
architecture Behavioral of subtractor_16bit is
component fulladder_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end component;
component twoscomplement is
Port (
A : in unsigned (15 downto 0);
C : out signed (15 downto 0)
);
end component;
signal n1 : STD_LOGIC_VECTOR(15 downto 0);
begin
twoscomplement_1: twoscomplement port map (a => a ,c => n1); --ERROR
fulladder_16bit_1: fulladder_16bit port map (a => a, b => n1, sum => sum , cin => cin, cout => cout, over => over);
end Behavioral;
However, I am receiving an error saying:
Error: type error near a; current type std_logic_vector; expected type unsigned.
Kindly help me to solve this problem.
As nobody is answering this and nobody is down voting it, I will answer.
Look at the error
Error: type error near a; current type std_logic_vector; expected type unsigned.
Now look at entity subtractor_16bit.
[...]
entity subtractor_16bit is
Port ( a : in STD_LOGIC_VECTOR(15 downto 0);
[...]
component twoscomplement is
Port (
A : in unsigned (15 downto 0);
[...]
twoscomplement_1: twoscomplement port map (a => a ,c => n1);
[...]
What do you see? twoscomplement expects an unsigned, while a is std_logic_vector! Just like the error says.
std_logic_vector and unsigned are two separate types. As VHDL is a strongly typed language, you cannot just put the data from one type to another. You need to use type conversion.
For unrelated types, you should implement a type conversion function. Or functions, if you want bidirectional conversion. E.g.
function (input : type_a) return type_b;
But in this case, std_logic_vector and unsigned have the same underlying type, std_logic. (std_ulogic actually since VHDL-2008 I believe.)
In that case you can convert from one type to another explicitly. E.g.
signal a_u : unsigned(y downto 0);
signal a_slv : std_logic_vector(y downto 0);
begin
a_u <= unsigned(a_slv);
Next, your not instantiating the twoscomplement component properly. The entity has a generic Nbits. By default you set it to 8. But in your architecture Behavioral of subtractor_16bit, you feed it with 16 bits, without changing the generic value. That doesn't work.
Also: twoscomplement has two ports: A and Y. But in subtractor_16bit you start using A and C. That's bad coding practice.
Finally, you can drop the component declarations. Just instantiate the entities from the library. E.g.
twoscomplement_1: entity work.twoscomplement [...]
So, subtractor_16bit should look something like this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity subtractor_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
cin : in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end entity;
architecture structural of subtractor_16bit is
use IEEE.NUMERIC_STD.ALL;
signal n1 : signed(a'range);
begin
twoscomplement_1: entity work.twoscomplement
generic map(
NBits => a'length
)
port map (
a => unsigned(a),
y => n1
);
fulladder_16bit_1: entity work.fulladder_16bit
port map (
a => a,
b => std_logic_vector(n1),
sum => sum,
cin => cin,
cout => cout,
over => over
);
end architecture;
...
HOWEVER this will still not work.
As you see on your entity twoscomplement, port A has a size of NBits, and port Y has a size of NBits+1. That is because you seem to want to keep 16-bit value precision. So when converting unsigned to signed, you need to add a 17th bit for the sign. As a result, the rest of you code will need to be modified!
.... But this can be fixed a different way. I will learn you something about two's complement: -a = not(a) + 1.
Proof (Take 4 bits signed precision):
0 = b'0000 => -0 is not(b'0000)+1 = b'1111'+1 = b'0000'
7 = b'0111 => -7 is not(b'0111)+1 = b'1000'+1 = b'1001'
-6 = b'1010' => 6 is not(b'1010)+1 = b'0101'+1 = b'0110'
See?
So now I will solve your puzzle for you:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity subtractor_16bit is
Port (
a : in STD_LOGIC_VECTOR(15 downto 0);
b : in STD_LOGIC_VECTOR(15 downto 0);
sum : out STD_LOGIC_VECTOR(15 downto 0);
cout : out STD_LOGIC;
over : out STD_LOGIC
);
end entity;
architecture structural of subtractor_16bit is
begin
fulladder_16bit_1: entity work.fulladder_16bit
port map (
a => a,
b => not(b),
sum => sum,
cin => '1',
cout => cout,
over => over
);
end architecture;
You will still need to change/fix the cout and over behavior...

Query on VHDL generics in packages

I have written a simple VHDL code to add two matrices containing 32 bit floating point numbers. The matrix dimensions have been defined in a package. Currently, I specify the matrix dimensions in the vhdl code and use the corresponding type from the package. However, I would like to use generic in the design to deal with matrices of different dimensions. For this I would have to somehow use the right type defined in the package. How do I go about doing this?
My current VHDL code is as below.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.mat_pak.all;
entity newproj is
Port ( clk : in STD_LOGIC;
clr : in STD_LOGIC;
start : in STD_LOGIC;
A_in : in t2;
B_in : in t2;
AplusB : out t2;
parallel_add_done : out STD_LOGIC);
end newproj;
architecture Behavioral of newproj is
COMPONENT add
PORT (
a : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
b : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
clk : IN STD_LOGIC;
sclr : IN STD_LOGIC;
ce : IN STD_LOGIC;
result : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
rdy: OUT STD_LOGIC
);
END COMPONENT;
signal temp_out: t2 := (others=>(others=>(others=>'0')));
signal add_over: t2bit:=(others=>(others=>'0'));
signal check_all_done,init_val: std_logic:='0';
begin
init_val <= '1';
g0: for k in 0 to 1 generate
g1: for m in 0 to 1 generate
add_instx: add port map(A_in(k)(m), B_in(k)(m), clk, clr, start, temp_out(k)(m), add_over(k)(m));
end generate;
end generate;
g2: for k in 0 to 1 generate
g3: for m in 0 to 1 generate
check_all_done <= add_over(k)(m) and init_val;
end generate;
end generate;
p1_add:process(check_all_done,temp_out)
begin
AplusB <= temp_out;
parallel_add_done <= check_all_done;
end process;
end Behavioral;
My package is as below
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;
package mat_pak is
subtype small_int is integer range 0 to 2;
type t22 is array (0 to 1) of std_logic_vector(31 downto 0);
type t2 is array (0 to 1) of t22; --2*2 matrix
type t22bit is array (0 to 1) of std_logic;
type t2bit is array (0 to 1) of t22bit; --2*2 matrix bit
type t33 is array (0 to 2) of std_logic_vector(31 downto 0);
type t3 is array (0 to 2) of t33; --3*3 matrix
end mat_pak;
Any suggestions would be welcome. Thank you.
There are some logical issues with your design.
First, there's some maximum number of ports for a sub-hierarchy a design can tolerate, you have 192 'bits' of matrix inputs and outputs. Do you really believe this number should be configurable?
At some point it will only fit in the very large FPGA devices, and shortly thereafter not fit there either.
Imagining some operation taking a variable number of clocks in add and parallel_add_done signifies when an aplusb datum is available comprised of elements of the matrix array contributed by all instantiated add components, the individual rdy signals are ANDed together. If the adds all take the same amount of time you could take the rdy from anyone of them (If you silicon is not that deterministic it would not be usable, there are registers in add).
The nested generate statements all assign the result of the AND between add_over(k,m) and init_val (which is a synthesis constant of 1). The effect or wire ANDing add_over(k.m) bits together (which doesn't work in VHDL and is likely not achievable in synthesis, either).
Note I also showed the proper indexing method for the two dimensional arrays.
Using Jonathan's method of sizing matrixes:
library ieee;
use ieee.std_logic_1164.all;
package mat_pak is
type matrix is array (natural range <>, natural range <>)
of std_logic_vector(31 downto 0);
type bmatrix is array (natural range <>, natural range <>)
of std_logic;
end package mat_pak;
library ieee;
use ieee.std_logic_1164.all;
use work.mat_pak.all;
entity newproj is
generic ( size: natural := 2 );
port (
clk: in std_logic;
clr: in std_logic;
start: in std_logic;
a_in: in matrix (0 to size - 1, 0 to size - 1);
b_in: in matrix (0 to size - 1, 0 to size - 1);
aplusb: out matrix (0 to size - 1, 0 to size - 1);
parallel_add_done: out std_logic
);
end entity newproj;
architecture behavioral of newproj is
component add
port (
a: in std_logic_vector(31 downto 0);
b: in std_logic_vector(31 downto 0);
clk: in std_logic;
sclr: in std_logic;
ce: in std_logic;
result: out std_logic_vector(31 downto 0);
rdy: out std_logic
);
end component;
signal temp_out: matrix (0 to size - 1, 0 to size - 1)
:= (others => (others => (others => '0')));
signal add_over: bmatrix (0 to size - 1, 0 to size - 1)
:= (others => (others => '0'));
begin
g0:
for k in 0 to size - 1 generate
g0x:
for m in 0 to size - 1 generate
add_instx: add
port map (
a => a_in(k,m),
b => b_in(k,m),
clk => clk,
sclr => clr,
ce => start,
result => temp_out(k,m),
rdy => add_over(k,m)
);
end generate;
end generate;
aplusb <= temp_out;
p1_add:
process (add_over)
variable check_all_done: std_logic;
begin
check_all_done := '1';
for k in 0 to size - 1 loop
for m in 0 to size -1 loop
check_all_done := check_all_done and add_over(k,m);
end loop;
end loop;
parallel_add_done <= check_all_done;
end process;
end architecture behavioral;
We find that we really want to AND the various rdy outputs (add_over array) together. In VHDL -2008 this can be done with the unary AND, otherwise you're counting on a synthesis tool to flatten the AND (and they generally do).
I made the assignment to aplusb a concurrent assignment.
So I dummied up an add entity with an empty architecture, the above then analyzes, elaborates and simulates, which shows that none of the connectivity has length mismatches anywhere.
I'm not quite sure to understand perfectly, but I'll try to answer anyway ;)
You can use unconstrained array like this:
package mat_pak is
type matrix is array(natural range <>, natural range <>) of std_logic_vector(31 downto 0);
end package mat_pack;
entity newproj is
Generic ( size : natural );
Port ( clk : in STD_LOGIC;
clr : in STD_LOGIC;
start : in STD_LOGIC;
A_in : in matrix(0 to size-1, 0 to size-1);
B_in : in matrix(0 to size-1, 0 to size-1);
AplusB : out matrix(0 to size-1, 0 to size-1);
parallel_add_done : out STD_LOGIC);
end newproj;

using sin and cos through the lookup table in VHDL

i'm using the sin/cos lookup table in VHDL known as sincos_lut.vhd and i'm getting an error when used with my code. I'm implementing my datapath and i need to perform sin and cos on an integer value. I do not know where my problem is but here is the code and error:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.MATH_REAL.all;
entity DFT is
port(
clk_en, clk, reset, Clock: std_logic;
t_sel,K_sel,sr_sel,si_sel,ld_t,ld_K,ld_sumreal,ld_sumimag,ld_angle: in std_logic;
N: in integer;
e: in std_logic_vector(3 downto 0);
outreal, outimag: out integer;
sig1, sig2: out std_logic
);
end DFT;
architecture str of DFT is
component Adder
Port( a, b: in integer;
f: out integer
);
end component;
component Reg
Port(
Clk: in std_logic;
ld: in std_logic;
a: in integer;
f: out integer
);
end component;
component Mul
Port(
a, b: in integer;
f: out integer
);
end component;
component LT
Port(
a, b: in integer;
sig: out std_logic
);
end component;
component Div
Port(
a, b: in integer;
f: out integer
);
end component;
component Mux
Port(
sel: in std_logic;
a, b: in integer;
f: out integer
);
end component;
component Mem
port( Clock: in std_logic;
Read: in std_logic;
Write: in std_logic;
Address: in integer;
Data_in: in integer;
Data_out: out integer
);
end component;
component sincos_lut Port
(
reset : in std_logic;
clk : in std_logic;
clk_en : in std_logic;
theta : in integer;
sin_data : out signed(integer);
cos_data : out signed(integer)
);
end component;
signal s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s20,s21,s22,s23,s24,s25,s26,s30,s31,s32,s33 : integer;
constant MATH_PI : real := 3.14159_26535_89793_23846;
begin
G1: Mux port map(K_sel,0,s1,s2);
G2: Mux port map(t_sel,0,s3,s4);
G3: Reg port map(Clk,ld_K,s2,s5);
G4: Reg port map(Clk,ld_t,s4,s6);
G5: LT port map(s5,N,sig1);
G6: LT port map(s6,N,sig2);
G7: Adder port map(s5,1,s1);
G8: Adder port map(s6,1,s3);
G9: Div port map(s5,N,s7);
G10: Mul port map(s7,s6,s8);
G11: Mul port map(s8,integer(MATH_PI),s9);
G12: Mul port map(s9,2,s10);
G13: Reg port map(Clk, ld_angle,s10,s11);
G14: Mem port map(Clock,'1','0',s6,0,s12);
G15: Mem port map(Clock,'1','0',s6,0,s13);
G16: Mul port map(s12,s33,s14);
G17: Mul port map(s13,s30,s15);
G18: Adder port map(s14,s15,s16);
G19: Mux port map(sr_sel,0,s17,s18);
G20: Reg port map(Clk, ld_sumreal,s18,s19);
G21: Adder port map(s16,s19,s17);
G22: Mul port map(s12, -1,s20);
G31: sincos_lut port map(reset, clk, clk_en, s11, s30, s31);
G32: sincos_lut port map(reset, clk, clk_en, s11, s32, s33);
G23: Mul port map(s20, s30, s21);
G24: Mul port map(s13, s33, s22);
G25: Adder port map(s21, s22,s23);
G26: Mux port map(si_sel,0,s24,s25);
G27: Reg port map(Clk, ld_sumimag,s25,s26);
G28: Adder port map(s23,s26,s24);
G29: Mem port map(Clock, '0','1',s5,outimag);
G30: Mem port map(Clk, '0','1',s5,outreal);
sincos_lut
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity sincos_lut is
port
(
reset : in std_logic;
clk : in std_logic;
clk_en : in std_logic;
theta : in integer;
sin_data : out signed(integer);
cos_data : out signed(integer)
);
end sincos_lut;
architecture rtl of sincos_lut is
signal theta_int : integer range 0 to 4095 := 0;
signal sin_data_int : signed(integer);
signal cos_data_int : signed(integer);
begin
theta_int <= theta;
process(reset,clk)
begin
if(reset = '1')then
sin_data_int <= to_signed(0,12);
cos_data_int <= to_signed(0,12);
elsif(rising_edge(clk)) then
if clk_en = '1' then
sin_data <= sin_data_int;
cos_data <= cos_data_int;
case theta_int is
end str;
Errors:
Error (10476): VHDL error at DFT.vhd(119): type of identifier "s30" does not agree with its usage as "SIGNED" type
Error (10558): VHDL error at DFT.vhd(119): cannot associate formal port "sin_data" of mode "out" with an expression
Error (10476): VHDL error at DFT.vhd(119): type of identifier "s31" does not agree with its usage as "SIGNED" type
Error (10558): VHDL error at DFT.vhd(119): cannot associate formal port "cos_data" of mode "out" with an expression
Line 119 is:
G31: sincos_lut port map(reset, clk, clk_en, s11, s30, s31);
Your errors are because s30 and s31 are integers and you are connecting them to a signed ports.
Kevin.
type of identifier "s30" does not agree with its usage as "SIGNED" type
This error is caused by mixing different types. The type of s30 is integer, but you are trying to map it to a port of type signed.
cannot associate formal port "sin_data" of mode "out" with an expression
This error is normally caused by "reading" an output port in your logic, but I don't see a clear reason for this error. Possibly this is related to your ports of type : signed(integer). Signed() is used for type conversion.
Your code isn't a Minimal, Complete, and Verifiable example. Note your sincos_lut doesn't analyze either.
signal s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16,s17,s18,s19,s20,s21,s22,s23,s24,s25,s26,s30,s31,s32,s33 : integer;
constant MATH_PI : real := 3.14159_26535_89793_23846;
signal signed_s30: signed (11 downto 0);
signal signed_s31: signed (11 downto 0);
signal signed_s32: signed (11 downto 0);
signal signed_s33: signed (11 downto 0);
begin
s30 <= to_integer(signed_s30);
s31 <= to_integer(signed_s31);
s32 <= to_integer(signed_s32);
s33 <= to_integer(signed_s33);
You can create signed versions of s30, s31, s32 and s33 and convert
and assign them to s30, s31, s32, s33.
Also note there were associated errors in the sincos_lut, both in port declarations and signal declarations. A type name doesn't represent a range constraint. These have been fixed by:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity sincos_lut is
port
(
reset : in std_logic;
clk : in std_logic;
clk_en : in std_logic;
theta : in integer;
sin_data : out signed(11 downto 0); -- integer);
cos_data : out signed(11 downto 0) -- integer)
);
end sincos_lut;
architecture rtl of sincos_lut is
signal theta_int : integer range 0 to 4095 := 0;
signal sin_data_int : signed(11 downto 0); -- integer);
signal cos_data_int : signed(11 downto 0); -- integer);
The range of the signed values (actually the length) is determined by the to_signed function calls in the process.
Note use package numeric_std function to_integer, and in dft:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_arith.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.math_real.all;
use ieee.numeric_std.all; -- never, never mix std_logic_arith/numeric_std
-- (see sincos_lut)
Type declarations in two different packages are unique regardless of whether they have the same name and base type or not. They are not compatible. If your tool let's you it is not compliant to the VHDL standard.
G31: sincos_lut port map(reset, clk, clk_en, s11, signed_s30, signed_s31);
G32: sincos_lut port map(reset, clk, clk_en, s11, signed_s32, signed_s33);
That lops of those errors, but reveals two more:
G29: Mem port map(Clock, '0','1',s5,outimag);
G30: Mem port map(Clk, '0','1',s5,outreal);
If you look at your mem component and the positional association list in the instance port maps you'll find you're missing an integer argument for both of these representing Address.
I don't think you've revealed enough of your 'precious' IP from someone to tell what should be connected here. It's part of the price in seeking help, showing what you got. When someone tells you it isn't a minimum example, in this case it would be throwing out component instantiations and signals not connected to the actual error reports.
Also note the promiscuous use of unconstrained integers which can end up implying 32 bit values in synthesis. You should be careful and constrain everything you can.
For instance defining the range constraint for the integer address going to the Mem component defines how big the memory is.
Dummy-ing up a signal Address, an integer and inserting it in the component allows dft to finish analyzing:
G29: Mem port map(Clock, '0','1',Address,s5,outimag);
G30: Mem port map(Clk, '0','1',Address,s5,outreal);
It's not possible to elaborate your design without dummy-ing up entity and architecture pairs for all your instantiated components or eliminating them (which would lead you to a second question later).
(And you could have produced integers from the sincos_lut entity/architecture pair, but without a range constraint that would have likely been a 32 bit value).

VHDL: can not have such operands in this context (sobel filter)

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
--use ieee.std_logic_unsigned.all;
--use ieee.std_logic_signed.all;
entity sobel is
port (
top_left_pixel : in std_logic;
top_middle_pixel : in std_logic;
top_right_pixel : in std_logic;
middle_left_pixel : in std_logic;
middle_right_pixel : in std_logic;
bottom_left_pixel : in std_logic;
bottom_middle_pixel : in std_logic;
bottom_right_pixel : in std_logic;
sobelx : out std_logic;
sobely : out std_logic
);
end entity sobel;
architecture noddy of sobel is
signal p1 : std_logic := top_left_pixel;
signal p2 : std_logic := top_middle_pixel;
signal p3 : std_logic := top_right_pixel;
signal p4 : std_logic := middle_left_pixel;
signal p6 : std_logic := middle_right_pixel;
signal p7 : std_logic := bottom_left_pixel;
signal p8 : std_logic := bottom_middle_pixel;
signal p9 : std_logic := bottom_right_pixel;
signal sobelx_s : integer;
signal sobely_s : integer;
begin
-- Same error on both these lines
sobelx_s <= (p3 - p1) + ((p6 & '0') - (p4 & '0')) + (p9 - p7);
sobely_s <= (bottom_left_pixel - top_left_pixel) + ((bottom_middle_pixel & '0') - (top_middle_pixel & '0')) + (bottom_right_pixel - top_right_pixel);
end architecture noddy;
I am trying to build a sobel filter in VHDL with very little experience. This entity is made just for trying it out with a test bench to see if the sobel-algorith works on the input data.
Any suggestions?
All answers are really appreciated, and if you could direct a complete VHDL beginner to something useful, you're welcome
That code looks familiar :) I thought architecture noddy was a bit unusual...
Try this (from the link above) instead:
entity sobel is
port (
top_left_pixel : in integer;
top_middle_pixel : in integer;
top_right_pixel : in integer;
middle_left_pixel : in integer;
middle_right_pixel : in integer;
bottom_left_pixel : in integer;
bottom_middle_pixel : in integer;
bottom_right_pixel : in integer;
sobelx : out integer;
sobely : out integer
);
end entity sobel;
architecture noddy of sobel is
begin -- architecture noddy
sobelx <= (-1*top_left_pixel)+(-2*middle_left_pixel)+(-1*bottom_left_pixel)
+(1*top_right_pixel)+(2*middle_right_pixel)+(1*bottom_right_pixel);
sobely <= (-1*top_left_pixel)+(-2*top_middle_pixel)+(-1*top_right_pixel)
+(1*bottom_left_pixel)+(2*bottom_middle_pixel)+(1*bottom_right_pixel);
end architecture noddy;
First of all, the Sobel operator is usually applied on a grayscale image using convolution. Or otherwise maybe you really want a binary image. So the Sobel matrix is something like:
-1 0 +1
-2 0 +2
-1 0 +1
for a horizontal change. You want to convolute this with your original image. Try having a grayscale input first and then maybe you can try with a binary image input.
The reason you are getting your VHDL errors is that you cannot add (+) or do any maths on std_logic or std_logic_vector. You need to use the unsigned and signed types (probably signed here) which overload the maths operators. Use the numeric_std library for that (your VHDL environment should have that; it's pretty standard).
If you have a real entity though, of which the inputs are real signals, they should be std_logic_vector. You then need to cast those to signed/unsigned by following this graph.

Resources