I have following piece of code in Vhdl now I want to redirect this signal S1 conditionally to the output port, I will be gratful if someone can guide me through this.
Gen: for index in 0 to 4 generate
signal s1 : ARRAY_TYPE; --- array of (0 to 7) std_logic_vector (7 downto 0);
begin
process(CLK)
begin
if (rising_edge (CLK)) then
S1(counter_index) <= S_in((index*8+7) downto (index*8));
end if;
end if;
end process;
end generate Gen;
I know we can use a process inside generate loop but is otherway around also possible! If I declare S1 as global signal it complains of connected to multi driven net? How this is different?
I will be really grateful if someone can guide me through this
Your for-generate loop (from 0 to 4) will be unrolled at elaboration so that what you end up with, effectively, is (leaving out the process code for brevity):
for index = 0:
signal s1_0 : ARRAY_TYPE; --- array of (0 to 7) std_logic_vector (7 downto 0);
s1_0(counter_index) <= S_in(7 downto 0);
for index = 1:
signal s1_1 : ARRAY_TYPE; --- array of (0 to 7) std_logic_vector (7 downto 0);
s1_1(counter_index) <= S_in(15 downto 8);
etc.
You get "copies" because you declared the signal inside the generate loop, each of which is local to just that generate block. When you try to make s1 "global" (not really global, which has a different connotation; just declared for the whole architecture), you get:
for index = 0:
s1(counter_index) <= S_in(7 downto 0);
for index = 1:
s1(counter_index) <= S_in(15 downto 8);
See what happened there? Those statements are concurrent, and assigning to the same bits. That's why you have problems with multiple drivers.
The problem appears to be counter_index. Either you need to index s1 with some combination of your loop index with your other index, as QuantumRipple suggested, or you need to create some intermediate signal, or something.
Note that if you're handling 32-bit data a byte at a time, you probably meant 0 to 3, not 0 to 4.
Although fru1tbat covers the solution to your problem, I wanted to cover your other question:
I know we can use a process inside generate loop but is otherway
around also possible!
You can use a for ... loop inside of a process statement as well. It functions and gets unrolled similarly to a for... generate statement, but inside of a process. It can also be used to implement more complex logic by using variables or overwriting assignments. Here is a syntax reference for it: http://www.ics.uci.edu/~jmoorkan/vhdlref/for_loop.html
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.
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.
I want to write a function in VHDL which is given the top few bits of a std_logic_vector and does stuff to them but it seems to be that the indexing of my function still starts counting at the bottom of the whole vector.
I can get around this by first assigning my vector to a temporary signal and using that but I'm worried that I don't understand what's going on here.
Could someone explain why a and b don't get the same output in the below?
architecture rtl of inds is
function top_bit (c : std_logic_vector) return std_logic is
begin
return c(c'length-1);
end top_bit;
signal temp : std_logic_vector(2 downto 0);
begin
temp <= input(3 downto 1);
a <= top_bit(temp);
b <= top_bit(input(3 downto 1));
end rtl;
If you give them the input "0100", you get a='0', b='1'.
If you give them the input "1000", you get a='1', b='0'.
So a=temp(2)=input(3) and b=input(2) which is input("length of c" -1).
I don't think this makes sense, can someone justify it for me.
Edit: if you replace the declaration line with:
function top_bit (c : std_logic_vector(2 downto 0)) return std_logic is
then it works as I'd expect.
I suppose the vector c takes it's indexing from the vector it's given.
I'd like to see a function which takes an arbitrary slice of a vector and returns the top bit of that slice.
You are using the 'length attribute, where you could be using 'high. I think this would do what you're asking for.
I've got a print out on my wall of the table here http://www.csee.umbc.edu/portal/help/VHDL/attribute.html as a reference for what attributes are available.
The issue, is that c'length returns the length of the vector which is not necessarily a valid index. For example, say I declared the following signal:
signal temp : std_logic_vector(7 downto 4);
This would cause a range error calling top_bit. As you note in your comment on scary_jeff's answer, not all vectors are x downto 0. They could be x downto y. Or they could even by 0 to x or x to y. Assuming that c'length-1 is the top bit is only true if c is declared as std_logic_vector(N-1 downto 0) (which you discovered in your answer).
Just as a clarification. scary_jeff's answer is the correct way. However, you need to resolve what is meant by "top_bit". What if you are given a to vector, such as:
signal temp : std_logic_vector(4 to 7)
What is top bit? Bit 4 or bit 7? If you use 'high, you'll get bit 7. Is this the top bit? If you want bit 4 to be the top bit, you'll need to use 'low.
lets say I have an n-bit array. I want to AND all elements in the array. Similar to wiring each element to an n-bit AND gate.
How do I achieve this in VHDL?
Note: I am trying to use re-usable VHDL code so I want to avoid hard coding something like
result <= array(0) and array(1) and array(2)....and array(n);
Thanks
Oshara
Solution 1: With unary operator
VHDL-2008 defines unary operators, like these:
outp <= and "11011";
outp <= xor "11011";
outp <= and inp; --this would be your case
However, they might not be supported yet by your compiler.
Solution 2: With pure combinational (and traditional) code
Because in concurrent code you cannot assign a value to a signal more than once, your can create a temp signal with an "extra" dimension. In your case, the output is one-bit, so the temp signal should be a 1D array, as shown below.
-------------------------------------------
entity unary_AND IS
generic (N: positive := 8); --array size
port (
inp: in bit_vector(N-1 downto 0);
outp: out bit);
end entity;
-------------------------------------------
architecture unary_AND of unary_AND is
signal temp: bit_vector(N-1 downto 0);
begin
temp(0) <= inp(0);
gen: for i in 1 to N-1 generate
temp(i) <= temp(i-1) and inp(i);
end generate;
outp <= temp(N-1);
end architecture;
-------------------------------------------
The inferred circuit is shown in the figure below.
Solution 3: With sequential code
This is simpler than solution 2, though you are now using sequential code to solve a purely combinational problem (but the hardware will be the same). You can either write a code similar to that in solution 2, but with a process and loop (the latter, in place of generate) or using a function. Because in sequential code you are allowed to assign a value to a signal more than once, the temp signal of solution 2 is not needed here.
If you have VHDL-2008 available, then reduction and is build into the
language as David Koontz and Pedroni have explained.
If you only have VHDL-2003 and prior available, then you can use a function
like:
function and_reduct(slv : in std_logic_vector) return std_logic is
variable res_v : std_logic := '1'; -- Null slv vector will also return '1'
begin
for i in slv'range loop
res_v := res_v and slv(i);
end loop;
return res_v;
end function;
You can then use the function both inside and outside functions with:
signal arg : std_logic_vector(7 downto 0);
signal res : std_logic;
...
res <= and_reduct(arg);
My favorite, non-VHDL-2008 solution is:
use ieee.std_logic_unsigned.all ; -- assuming not VHDL-2008
. . .
result <= '1' when not MyArray = 0 else '0' ;
With VHDL-2008, I recommend that you use the "and" reduction built-in (see Pedroni's post) and use the IEEE standard package "ieee.numeric_std_unsigned.all" instead of the shareware package "std_logic_unsigned".
I have a FIFO who's size is determined according to a parameter in the package:
signal fifo : std_logic_vector(FIFO_SIZE*8 -1 downto 0);
I also have a 4 bit vector (numOfBytes) saying how many bytes are in the FIFO at any given time (up to 8).
I want the data out (a single byte) from the FIFO to be determined according the numOfBytes signal:
Do <= fifo(to_integer(unsigned(numOfBytes)*8 -1 downto to_integer(unsigned(numOfBytes)*8 -8) when numOfBytes /= x"0" else (others => '0');
when simulating, this works well, however when I try to synthesis it (using Synopsys DC) I get an elaboration error upon linking the design saying "Constant value required (ELAB-922)".
The ELAB code means "This error message occurs because an expression in the indicated line of your RTL description does not evaluate to a constant value, as required by the language."
How else can I make the output mux so it will undergo synthesis?
if not for the parameter i'd change the Do line to a regular mux, but it can't work with the parameters. (I can't call fifo(63 downto 54) when fifo is 4 byte...)
p.s.
I tried working with conv_integer in the beginning, but changed to to_integer(unsigned())due to answers found on the web.
Signal indexes used to construct a range have to be compile-time constants for synthesis to accept them.
There are two ways to solve this problem:
1) Change your FIFO to use an array. This is the standard way of declaring any form of memory, such as a FIFO.
type fifo_type is array(0 to FIFO_SIZE-1) of std_logic_vector(8-1 downto 0);
signal fifo : fifo_type;
...
Do <= fifo(to_integer(unsigned(numOfBytes))-1) when(numOfBytes/=0) else (others=>'0');
2) Use a loop to convert the variable into a constant. This is a common way to code a generic mux.
Do <= (others=>'0');
for i in 0 to FIFO_SIZE-1 loop
if(numOfBytes=i+1) then
Do <= fifo((i+1)*8-1 downto i*8);
end if;
end loop;
I would recommend the first approach for larger, memory-based FIFOs, and the second for smaller, register-based ones.
If the FIFO created with a number of bytes, instead of combining it into the same std_logic_vector then Synopsys DC may be able to handle it. Code could look like:
library ieee;
use ieee.numeric_std.all;
architecture syn of mdl is
... Declaration of FIFO_SIZE natural constant
type fifo_t is array(natural range <>) of std_logic_vector(7 downto 0);
signal fifo : fifo_t(FIFO_SIZE - 1 downto 0);
begin
... Handling FIFO insert and remove
Do <= fifo(to_integer(unsigned(numOfBytes))) when numOfBytes /= x"0" else (others => '0');
end architecture;
If you don't need a runtime-dynamic size to the FIFO, use a generic on your entity.
If you truly need a dynamic sized FIFO, you'll have to use a loop in a process as someone else said. But be very careful how you use such a FIFO, as if you change the size of it while someone is reading or writing, bad things may happen!