I am developing a 10 point moving average filter for an assignment. I am taking small steps so that I can be sure each stage of my code is working. My first step is to take an input which is a standard logic vector (5 bits) and convert it to a signal of type integer for processing before converting back to a standard logic vector for output. My first block of code is:
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
entity AveFilter is
port( CLK : in STD_LOGIC;
RST : in STD_LOGIC;
ADC_In : in STD_LOGIC_VECTOR ( 4 downto 0);
AveOut : out STD_LOGIC_VECTOR ( 4 downto 0)
);
end AveFilter;
architecture Behavioral of AveFilter is
signal adc_sum : integer := 0;
type Circ_Buf is array (0 to 9) of STD_LOGIC_VECTOR (4 downto 0);
signal ave_buf : Circ_Buf;
begin
process (CLK, RST, ADC_In)
variable idx : integer := 5;
begin
ave_buf(0) <= ADC_In;
adc_sum <= to_integer(unsigned(ave_buf(0)));
AveOut <= std_LOGIC_VECTOR(to_unsigned(adc_sum, AveOut'length));
end process;
end architecture;
The above code simply takes the input value and assigns to the output; I have tested this with modelsim and it works as expected. I can also assign various hard coded values to adc_sum and they also apear on the out put as expected.
The problem I have is when I modify the code so that the current adc input is added to the previous value of adc_sum and then stored in adc_sum ie by doing this:
adc_sum <= adc_sum + to_integer(unsigned(ave_buf(0)));
When I view AveOut in model sim the values are always XXXX. I have looked at some VHDL examples and it looks like and I beleive that I should be able to perorm the above operation. Could someone please give me a clue as to what I'm missing here?
Thanks
Andrew
ave_buf is probably undefined at the beginning. Try initializing it. If this works, you should also implement reset on it. Also, you should take action on rising edge of the clock. And ADC_In is unnecessary in the sensitivity list.
Related
I want to have a loop that runs the all lines of my code and also that runs every position of all lines.
My problem is in selecting the line that the loop will run, and I want to have simple way to do it without making to write every single line one-by-one, cause the final code will have 66 lines to scan.
Hope you can help me.
Entity of this code will have 66 lines, but I'm just testing it this 10 lines right now:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lshift is
port( RED_Buffer1 : in std_logic_vector(6 downto 0);
RED_Buffer2 : in std_logic_vector(6 downto 0);
RED_Buffer3 : in std_logic_vector(6 downto 0);
RED_Buffer4 : in std_logic_vector(6 downto 0);
RED_Buffer5 : in std_logic_vector(6 downto 0);
IR_Buffer1 : in std_logic_vector(6 downto 0);
IR_Buffer2 : in std_logic_vector(6 downto 0);
IR_Buffer3 : in std_logic_vector(6 downto 0);
IR_Buffer4 : in std_logic_vector(6 downto 0);
IR_Buffer5 : in std_logic_vector(6 downto 0);
output : out bit_vector(1 downto 0));
end lshift;
What I have done so far but with no success:
ARCHITECTURE main OF lshift IS
SIGNAL condition1: boolean;
signal valor : std_ulogic;
BEGIN
PROCESS(IR_Buffer5)
BEGIN
FOR I IN 1 TO 5 LOOP
FOR J IN 1 TO 5 LOOP
CONSTANT linha_cond : string(1 to 12) := string(("RED_Buffer") && I);
IF (linha_cond(J) = '1') THEN
output <= "01";
END IF;
END LOOP;
END LOOP;
END PROCESS;
END main;
The purpose of this answer is to demonstrate indexing the subelement values of RED_Buffer1 through RED_Buffer5. Without the purpose of the code being revealed this could easily prove to be an XY Problem question.
While it is possible to organize RED_Buffer1 through RED_Buffer5 into a value that can be indexed as shown below, there are other issues as well.
library ieee;
use ieee.std_logic_1164.all;
entity lshift is
port (
red_buffer1: in std_logic_vector (6 downto 0);
red_buffer2: in std_logic_vector (6 downto 0);
red_buffer3: in std_logic_vector (6 downto 0);
red_buffer4: in std_logic_vector (6 downto 0);
red_buffer5: in std_logic_vector (6 downto 0);
ir_buffer1: in std_logic_vector (6 downto 0);
ir_buffer2: in std_logic_vector (6 downto 0);
ir_buffer3: in std_logic_vector (6 downto 0);
ir_buffer4: in std_logic_vector (6 downto 0);
ir_buffer5: in std_logic_vector (6 downto 0);
output: out bit_vector (1 downto 0)
);
end entity lshift;
architecture indexed_array of lshift is
signal condition1: boolean;
signal valor: std_ulogic;
type lbuffer is array (1 to 5) of std_logic_vector (6 downto 0);
signal red_buffer: lbuffer;
begin
red_buffer <= (red_buffer1, red_buffer2, red_buffer3, red_buffer4,
red_buffer5);
process (red_buffer)
begin
for i in 1 to 5 loop
for j in red_buffer'range loop
if red_buffer(i)(j) = '1' then
output <= "01";
end if;
end loop;
end loop;
end process;
end architecture indexed_array;
How the indexing is implemented here
A composite type (lbuffer) having the requisite number of elements with required element subtype is declared. This is possible because the declarations for ports RED_Buffer1 through RED_Buffer5 share a common subtype indication. Assignment to elements of an object of the type lbuffer would be compatible, having matching elements between the target and right hand expression.
A signal red_buffer with a type mark of lbuffer is declared.
A concurrent assignment was made to the signal in a concurrent signal assignment statement in the architecture statement part from an aggregate. The association in the aggregate is positional. It could as easily use named association:
-- red_buffer <= (red_buffer1, red_buffer2, red_buffer3, red_buffer4,
-- red_buffer5);
red_buffer <= (1 => red_buffer1, 2 => red_buffer2, 3 => red_buffer3,
4 => red_buffer4, 5 => red_buffer5);
The type of the aggregate is taken from context, here the assignment statement where red_buffer has the subtype lbuffer.
A selected element of the composite red_buffer is selected by an index name (red_buffer(i)). A subelement of red_buffer(i) is selected by use of an indexed name where the name red_buffer(i) where 'iis a constant using 'j from the inner loop - red_buffer(i)(j).
Note the range of the j parameter doesn't match the index range of subtype of the lbuffer element subtype here identical to the subtype of RED_Buffer1 through RED_Buffer5. This signifies a further potential semantic issue with the original code, whose purpose isn't made clear here. The only hint present in the original code comes from linha_cond where linha means line in Portuguese or Catalan indicating j is used to index within a 'line'.
The original code fails for two reasons
First an object can't be declared inline in VHDL. The for loop parameter is dynamically elaborated from an implicit declaration, the loop parameter is only visible within the loop statement's sequence of statements. The syntax doesn't allow for additional object declarations.
Second a name for a object declaration is conveyed in an identifier list consisting of one or more identifiers which are lexical elements (lexemes) that cannot be manipulated programmatically.
Other semantic issues with the question's code
The assignment to output without the passage of time doesn't appear useful.
A process statement is an independently executing concurrent statement wherein the loop statement containing an assignment to the same signal output will overwrite the projected output waveform for elements of output without any intervening passage of time.
There's only one entry in a projected output waveform queue for any particular simulation time. A simulation cycle consists of signal updates followed by the resumption and subsequent suspension of any processes sensitive to signal updates. The purpose is to emulate parallelism in hardware while describing behavior with sequential statements.
Here that would mean output would be updated to the value "01" if any of the if statement conditions in the unrolled loops evaluate to TRUE. That's likely not the intended behavior (without more information from the original poster).
Also note there is no output assignment to a different value and no default or otherwise assigned value. For synthesis this would represent a hold over delay on output until a '1' is first found.
In both cases this refers to an implicit latch for output.
This issue with the sample code can't be addressed without knowing how it is supposed to work and the only hint that has been shown here on Stackoverflow to date is by a question deleted by the user requiring 10K+ reputation to access (others will see aPage not found message, see revision 1).
Also concepts conveyed from programming or scripting languages don't generally port to Hardware Description Languages which are generally formal notations defined self-referentially (here in IEEE Std 1076, the VHDL Language Reference Manual) requiring inculcation or persistent effort to learn. HDLs generally describe hardware behaviorally and structurally not by programmatic equivalence.
Please see the code below:
....
port(
the_input: in std_logic_vector(0 to 3));
...
type dummy_array is array (0 to 2) of std_logic_vector (0 to 7);
signal ins_dummy: dummy_array := ( 8x"1", 8x"2", 8x"3");
...
Now I want to access the elements of this array using bits the_input(0 to 1). How can I do this? as I know array accepts integers as arguments, but this input is std_logic. I tried many solution available on different forums but nothing seems to be working. For example when I apply this: to_integer(unsigned(the_input(0 to 1))), result is zero.
What is happening? I don't know. Any suggestions?
Using the small testbench below, I was able to access elements of the array using the method you mentioned -> some_array(to_integer(unsigned(some_signal))).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
use ieee.std_logic_textio.all;
entity test is
end entity test;
architecture behav of test is
signal the_input : std_logic_vector(0 to 3);
signal test_sig : std_logic_vector(7 downto 0);
type dummy_array is array(0 to 2) of std_logic_vector(7 downto 0);
signal ins_dummy : dummy_array := (x"01", x"02", x"03");
begin
test_sig <= ins_dummy(to_integer(unsigned(the_input)));
process
begin
wait for 1 ns;
the_input <= "0000";
wait for 1 ns;
the_input <= "0001";
wait for 1 ns;
the_input <= "0010";
end process;
end architecture behav;
However, this is a simulation and a synthesizer may complain because the range of the port the_input is larger than the number of possible array options. You might have to add logic to ensure that the array indices which are "out of bounds" cannot be accessed. Hope that helps. Possibly try:
test_sig <= ins_dummy(to_integer(unsigned(the_input))) when (the_input < 3) else
others => '0';
I want to use dynamic range of array , so using "N" for converting an incoming vector signal to integer. Using the specifc incoming port "Size" gives me an error, while fixed vector produces perfect output.
architecture EXAMPLE of Computation is
signal size :std_logic_vector (7 downto 0);
process (ACLK, SLAVE_ARESETN) is
variable N: integer:=conv_integer ("00000111") ; ---WORKING
--variable N: integer:=conv_integer (size) ; -- Not working
type memory is array (N downto 0 ) of std_logic_vector (31 downto 0 );
variable RAM :memory;
Only reason to do this type of coding is send as much data as possible to FPGA .As I need to send Data from DDR to Custom IP via DMA in vivado may be more than 100 MB. so kindly guide me if I am trying to implement in wrong way as stated above.
You can't do that in VHDL. What kind of hardware would be generated by your code? If you don't know, the synthesizer won't either.
The way to do this kind of thing is to set N to the largest value you want to support, and use size in your logic to control your logic appropriately. It's difficult to give more pointers without more information, but as an example, you could use a counter to address your ram, and have it reset when it's greater than size.
Update
Here's a counter example. You have to make sure that size doesn't change while operating or it will fall into an unknown state. A real design should have reset states to ensure correct behaviour.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity example is
port (
clk : std_logic;
rst : in std_logic;
size : in unsigned(7 downto 0);
wr : in std_logic;
din : in std_logic_vector(31 downto 0)
);
end entity;
architecture rtl of example is
signal counter : unsigned(7 downto 0);
type ram_t is array(0 to 255) of std_logic_vector(31 downto 0);
signal ram : ram_t;
begin
RAM_WR: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= (others => '0');
else
if wr = '1' then
ram(to_integer(counter)) <= din;
if counter = size then
counter <= (others => '0');
else
counter <= counter + 1;
end if;
end if;
end if;
end if;
end process RAM_WR;
end architecture rtl;
I believe you can only have a generic an array constraint in a process. Otherwise, the compiler cannot elaborate.
In a function or procedure, you can have truly variable array bounds.
This is a code for two 6 bit serial adder.It acts like a scoreboard.iam getting a compiling error " cannot read output q ".please help me out of this.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity board IS
port
(
C: in std_logic;
h : in std_logic_vector(5 downto 0);
q : out std_logic_vector(5 downto 0)
-- s,cout : out std_logic
);
end board;
architecture archi of board is
signal tmp: std_logic_vector(5 downto 0);
begin
process(C)
begin
if(C'event and C='1') then
tmp<= std_logic_vector (unsigned(q) + unsigned(h));
end if;
end process;
q<=tmp;
end archi;
For some reason (why?) you cannot read from output ports directly. Create an internal signal, e.g. q_i, replace all q by q_i and assign the internal signal to the output port, i.e. q <= q_i.
On a further note, your tmp signal is not necessary. You can write q_i <= std_logic_vector((unsigned(q_i) + unsigned(h)); in a clocked process.
You should be using numeric_std rather than std_logic_unsigned. std_logic_unsigned is not an official ieee supported package. At the top of your file do this and your problems should go away:
use ieee.numeric_std.all;
Also don't put signal h in your process sensitivity list. That process is a clocked process and you shouldn't have any signal but your clock and an asynchronous reset in the sensitivity list (if you're using an async reset). You don't need a reset at all here.
Ok another question in VHDL. Below is my code. Suppose that I want my input stored in ram. And lets say I want to add two of them. (do not give emphasis on it, later on it will be replaced). This is my code:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
USE ieee.numeric_std.ALL;
use work.my_package.all;
entity landmark_1 is
generic
(data_length :integer := 8;
address_length:integer:=3 );
port ( clk:in std_logic;
vin:in std_logic;
rst:in std_logic;
flag: in std_logic;
din: in signed(data_length -1 downto 0);
done: out std_logic
);
end landmark_1;
architecture TB_ARCHITECTURE of landmark_1 is
component ram IS
generic
(
ADDRESS_WIDTH : integer := 4;
DATA_WIDTH : integer := 8
);
port
(
clock : IN std_logic;
data : IN signed(DATA_WIDTH - 1 DOWNTO 0);
write_address : IN unsigned(ADDRESS_WIDTH - 1 DOWNTO 0);
read_address : IN unsigned(ADDRESS_WIDTH - 1 DOWNTO 0);
we : IN std_logic;
q : OUT signed(DATA_WIDTH - 1 DOWNTO 0)
);
end component;
signal inp1,inp2: matrix1_t(0 to address_length);
signal out_temp: signed(data_length-1 downto 0);
signal k:unsigned(address_length-1 downto 0);
signal i: integer range 0 to 100:=0;
begin
read1:ram generic map( ADDRESS_WIDTH=>address_length, DATA_WIDTH=>data_length) port map (clk,din,k,k,vin,out_temp);
inp1(i)<=out_temp;
process (clk)
begin
if (clk'event and clk='1') then
if (flag='1') then out_temp<=inp1(0)+inp1(1);
end if;
end if;
end process ;
end TB_ARCHITECTURE;
Below are my questions:
Why to use that ram and not just do inp(i)<=din; . I think that it will help synthesizer understand that this is a ram, but what else? Moreover, do I need inp1 registers. And if I a going to use them, again why use ram as an intermediate?
If inp1 is unnecessary, how I am going to fetch these two elements in my process? I mean I need something like ram(address1)+ram(address2), right?
Below is my ram_code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY ram IS
GENERIC
(
ADDRESS_WIDTH : integer := 4;
DATA_WIDTH : integer := 8
);
PORT
(
clock : IN std_logic;
data : IN signed(DATA_WIDTH - 1 DOWNTO 0);
write_address : IN unsigned(ADDRESS_WIDTH - 1 DOWNTO 0);
read_address : IN unsigned(ADDRESS_WIDTH - 1 DOWNTO 0);
we : IN std_logic;
q : OUT signed(DATA_WIDTH - 1 DOWNTO 0)
);
END ram;
ARCHITECTURE rtl OF ram IS
TYPE RAM IS ARRAY(0 TO 2 ** ADDRESS_WIDTH - 1) OF signed(DATA_WIDTH - 1 DOWNTO 0);
SIGNAL ram_block : RAM;
BEGIN
PROCESS (clock)
BEGIN
IF (clock'event AND clock = '1') THEN
IF (we = '1') THEN
ram_block(to_integer(unsigned(write_address))) <= data;
END IF;
q <= ram_block(to_integer(unsigned(read_address)));
END IF;
END PROCESS;
END rtl;
3.can anyone tell me why the q (output) is estimated one clock later?
EDIT: To sum up,I was told that I should use a ram and this is my implementation. The question is what I have gained by changing my inp1(i)<=din; when I inserted the ram model. And there fore how can I use it? (before using the ram I waws just wrote inp1(i)+inp2(i+1) for example).
EDIT2: PACKAGE FOR TYPES.
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
package my_package is
type matrix1_t is array(integer range<>) of signed(7 downto 0);
type big_matrix is array(integer range<>) of signed(23 downto 0);
type matrix2d is array (integer range<>) of big_matrix(0 to 3);
end my_package;
Why to use that ram and not just do inp(i)<=din;
In real world designs you use RAMs to store large amounts of data because they are smaller (physically, on the chip) that arrays of flip flops. During the synthesis process the RAM is replaced by one from your vendor's library. This RAM looks rather small, but I'm guessing you've been told to use one as an exercise.
Moreover, do I need inp1 registers. And if I a going to use them, again why use ram as an intermediate?
I'm not quite sure what imp1 is, as I don't know what a matrix_t is, but I'm guessing it's a register version of the RAM. In which case it's redundant.
If inp1 is unnecessary, how I am going to fetch these two elements in my process? I mean I need something like ram(address1)+ram(address2), right?
...and there's the real issue. You need to ask yourself 'If you can't read more that one thing in a cycle, how do you add two numbers?'
can anyone tell me why the q (output) is estimated one clock later?
Because that's how RAMs work. You apply an address in one cycle, and the data appears some cycles later (normally one, but not always)
These are real issues that you'll face in real designs. RAMs are necessary because of their smaller size. You need to know the issues that surround using them and how to work with them.
You aren't setting i to anything other than 0 so you will only ever assign to inp1(0).
Assuming the RAM is there to store many values, and you need to read two of them every clock cycle in order to do your adding, you need 2 RAM blocks (or a single dual-ported one) and then put the two addresses into those RAM blocks. The next cycle the two values you want will appear on the data outputs and you can sum them.
The clock-cycle delay you observe is in the nature of synchronous RAMs (which is what most FPGAs have for their "large storage") - some can create smaller asynchronous RAMs where the data appears a short delay after the read address changes, completely asynchronously to the clock.
I assume you're trying to represent a RAM with the signal inp1. However, the signal that represents the RAM is ram_block in your ram entity.
You are using the entity in a strange way because you connect the signal k as read and write address. There are two problems with that. Firstly, k doesn't seem to be driven anywhere in your design. Secondly, you probably don't want the two addresses to be the same.
I assume you want to write some values to the RAM and at the same time read two values and add them up. I suggest you use a process that sets a write address and a process that sets a read address. You also need at least one register with the width of the RAM output. The first value you read from the RAM is stored in that register. Then you add the value in that register and the second value read from the RAM and store the result in a different register.