I have used VHDL all my life and only been using Verilog for a short time, I have to create a logic in Verilog for a very large array and assign it to 1 or 0 depending on the condition of an input.
Here is my VHDL code
if (data_track == '1' ) then
my_array(MAX-1:MIN) <= (others=> '1');
else
my_array(MAX-1:MIN) <= (others=> '0');
end if;
MAX and MIN are parameters for the block, set during the synthesis depending on the type of system we are accessing.
Is there a way to do this in Verilog easily?
A mix of parameter with curly braces will help in resolving (the inner curly brace will act as replication operator)
Code eg:
parameter MAX = 16;
assign high_val = 1'b1;
assign low_val = 1'b0;
if ( data_track ==1'b1)
my_array[MAX-1:MIN] <= {MAX{high_val}};
else
my_array[MAX-1:MIN] <= {MAX{low_val}};
Here in the above code the if statement with curly brace will propogate MSB to LSB with 1 values resulting in all 1's in our case 16 then result will be a 16'b1111111111111111 and it is the vice versa for else condition
Assuming that data_track is one bit wide, then this can be collapsed into one line by replicating the data_track input and assigning it to my_array:
assign my_array[MAX-1:MIN] = {(MAX-MIN){data_track}};
Related
I am trying to use aggregate assignments within a conditional assignment statement in the lines labelled "PROBLEMATIC LINE" in the following code implementation for a priority encoder module.
library ieee;
use ieee.std_logic_1164.all;
entity SN74LS148 is -- 8 to 3 line priority encoder module
port(EI : in std_logic; -- input enable
input : in std_logic_vector(0 to 7); -- 8 bit input bus
A : out std_logic_vector(2 downto 0); -- 3 output bits
GS, EO : out std_logic -- valid bit, enable output
);
end SN74LS148;
architecture behavioral of SN74LS148 is
signal truth_table : std_logic_vector(2 downto 0);
begin
truth_table <= "HHH" when input = (others => 'H') else -- PROBLEMATIC LINE
"LLL" when input(7) = 'L' else
"LLH" when input(6) = 'L' else
"LHL" when input(5) = 'L' else
"LHH" when input(4) = 'L' else
"HLL" when input(3) = 'L' else
"HLH" when input(2) = 'L' else
"HHL" when input(1) = 'L' else
"HHH" when input(0) = 'L' else
"XXX";
A <= truth_table when EI = 'L' else -- device enabled (active low)
"HHH" when EI = 'H' else -- device disabled (all outputs inactive)
"XXX";
GS <= 'H' when EI = 'H' -- invalid when device disabled
or input = (others => 'H') else -- or none of the lines asserted (PROBLEMATIC LINE)
'L';
EO <= 'L' when EI = 'L' and input = (others => 'H') else -- PROBLEMATIC LINE
'H';
end behavioral;
I am using the GHDL compiler. The error that I am getting is
encoder8x3.vhd:28:43: 'others' choice not allowed for an aggregate in this context
truth_table <= "HHH" when input = (others => 'H') else
^
encoder8x3.vhd:46:47: 'others' choice not allowed for an aggregate in this context
or input = (others => 'H') else -- or none of the lines asserted
^
encoder8x3.vhd:50:45: 'others' choice not allowed for an aggregate in this context
EO <= 'L' when EI = 'L' and input = (others => 'H') else
^
I guess I can fix this easily by hardcoding the inputs but what I want to know is why I am getting this error when the size of input has been specified in the port. This is not an ambiguity issue right ?
No, it is an ambiguity issue.
See IEEE Std 1076-1993 7.3.2.2 Array aggregates
The subtype of an array aggregate that has an others choice must be determinable from the context. That is, an array aggregate with an others choice may only appear
a. As an actual associated with a formal parameter or formal generic declared to be of a constrained array subtype (or subelement thereof)
...
Here the actual is your array aggregate associated with a parameter of the subprogram parameter for the overloaded equality operator, which is unconstrained. The type mark of that parameter would be the type std_logic_vector, while this would become a subtype in -2008 to allow subtype resolution specification it'd be unconstrained and the language of -2008 9.3.3.3 Array aggregates has been changed:
The index range of an array aggregate that has an others choice shall be determinable from the context.
That actually implies what's important here, the length of the aggregate array value. See 7.2.2 Relational operators:
Two scalar values of the same type are equal if and only if the values are the same. Two composite values of the same type are equal if and only if for each element of the left operand there is a matching element of the right operand and vice versa, and the values of matching elements are equal, as given by the predefined equality operator for the element type.
These rules also tell us the std_logic weak driving 'H' or 'L' enumeration values either as a scalar or an element of a composite value are not equal to the strong driving '1' and '0' values respectively.
As equality operator is defined by VHDL (7.2.2 of IEEE-1076-1993), there is no direct constraint between operands. For instance, if both operands are of the same array type, they may be not the same length (and equality will be always false), if they are of same length, elements are matched in order (whatever the range of array). This gives no strong constraint between operands.
In some contexts, literal array aggregates with others can be determined from context (initializations, assignments, etc.). Valid cases are listed in 7.3.2.2. Equality operator operands is not one of them.
You may still write an aggregate with an explicit range, for instance input = (input'range => 'H').
I am writing a VHDL Program for 4:1 MUX and am facing a error on the line where process clause starts
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mux_41 is
Port ( inp : in STD_LOGIC_VECTOR (0 downto 3);
outp : out STD_LOGIC;
sel : in STD_LOGIC_VECTOR (1 downto 0));
end mux_41;
architecture Behavioral of mux_41 is
begin
Process(inp[0],inp[1],inp[2],inp[3],sel[0],sel[1])
begin
if(sel = "00")
then outp <= inp[0];
elsif(sel = "01")
then outp <= inp[1];
elsif(sel = "10")
then outp <= inp[2];
else outp <= inp[3];
end if;
end process;
end Behavioral;
Is this the right way to pass sensitivity list to process?
In VHDL when you want to access to a particular element of an array (std_logic_vector are array), you have to use () instead of [].
Process(inp(0),inp(1),inp(2),inp(3),sel(0),sel(1))
begin
if(sel = "00")
then outp <= inp(0);
elsif(sel = "01")
then outp <= inp(1);
elsif(sel = "10")
then outp <= inp(2);
else outp <= inp(3);
end if;
end process;
The OP doesn't show the complete error message.
It appears to be in the sensitivity list for the process where inp is a signal_name and the particular parser doesn't use syntactic predicates:
IEEE Std 1076-2008 10.2 Wait statements
sensitivity_list ::= signal_name { , signal_name }
and here the selected names (8.3) are all static names (8.1) and all the elements of both sel and inp are evaluated in the process if statement (10.8) and should be included in the sensitivity set (10.2).
1.3.2 Syntactic description
The form of a VHDL description is described by means of context-free syntax using a simple variant of the Backus-Naur form (BNF); in particular:
...
g) If the name of any syntactic category starts with an italicized part, it is equivalent to the category name without the italicized part. The italicized part is intended to convey some semantic information. For example, type_name and subtype_name are both syntactically equivalent to name alone
...
It's possible to write a parser that uses a symbol table containing declarations of named entities (which precede the use of a name in a description). It simplifies both syntactical and semantic analysis while allowing the rules of visibility and scope to be tracked.
In any event not using syntactic predicates results in a different error message. Instead of an error describing a signal as not having a signature you get an error message saying the signature is malformed or isn't applicable (there are several rules that might be applicable without the syntactic predicates).
The error actually occurs for the first left square bracket. Selected names uses parentheses (round brackets in parts or Europe) instead of square brackets. Also inp by itself has elements 3 downto 0 or 0 to 3 (noting inp : in STD_LOGIC_VECTOR (0 downto 3) has a null range (5.2.1) and no elements).
5.2.1 pargraphs 3 and 4:
A range specifies a subset of values of a scalar type. A range is said to be a null range if the specified subset is empty.
The range L to R is called an ascending range; if L > R, then the range is a null range. The range L downto R is called a descending range; if L < R, then the range is a null range. ...
With a process sensitivity list a process statement (11.3) is assumed to have a single implicit wait statement as it's last sequential statement. The rule for constructing the sensitivity set for the implicit wait statement in a process statement are found in 10.2 Wait statement, where the implicit wait statement will use the longest static prefix (8.1) of any signal name in the process sensitivity list and would be equivalent to process (sel, inp).
11.3 Process statement paragraph 4:
If a process sensitivity list appears following the reserved word process, then the process statement is assumed to contain an implicit wait statement as the last statement of the process statement part; this implicit wait statement is of the form
wait on sensitivity_list ;
where the sensitivity list is determined in one of two ways. If the process sensitivity list is specified as a sensitivity list, then the sensitivity list of the wait statement is that following the reserved word process. ...
10.2 Wait statement paragraphs 3 and 4:
The sensitivity clause defines the sensitivity set of the wait statement, which is the set of signals to which the wait statement is sensitive. Each signal name in the sensitivity list identifies a given signal as a member of the sensitivity set. Each signal name in the sensitivity list shall be a static signal name, and each name shall denote a signal for which reading is permitted. If no sensitivity clause appears, the sensitivity set is constructed according to the following (recursive) rule:
The sensitivity set is initially empty. For each primary in the condition of the condition clause, if the primary is
— A simple name that denotes a signal, add the longest static prefix of the name to the sensitivity set.
— An expanded name that denotes a signal, add the longest static prefix of the name to the sensitivity set.
— A selected name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set.
— An indexed name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set and apply this rule to all expressions in the indexed name.
— A slice name whose prefix denotes a signal, add the longest static prefix of the name to the sensitivity set and apply this rule to any expressions appearing in the discrete range of the slice name.
...
This rule is also used to construct the sensitivity sets of the wait statements in the equivalent process statements for concurrent procedure call statements (11.4), concurrent assertion statements (11.5), and concurrent signal assignment statements (11.6). Furthermore, this rule is used to construct the sensitivity list of an implicit wait statement in a process statement whose process sensitivity list is the reserved word all (11.3).
What this tells us is that the longest static prefix is sufficient in the sensitivity list.
8.1 paragraph 7:
A static signal name is a static name that denotes a signal. The longest static prefix of a signal name is the name itself, if the name is a static signal name; otherwise, it is the longest prefix of the name that is a static signal name. ...
With a non-null range for inp, using parentheses instead of square brackets your mux_41 could be expressed:
library ieee;
use ieee.std_logic_1164.all;
entity mux_41 is
port (
inp: in std_logic_vector (3 downto 0);
outp: out std_logic;
sel: in std_logic_vector (1 downto 0)
);
end entity mux_41;
architecture behavioral of mux_41 is
begin
process (sel, inp)
begin
if sel = "00" then
outp <= inp(0);
elsif sel = "01" then
outp <= inp(1);
elsif sel = "10" then
outp <= inp(2);
else
outp <= inp(3);
end if;
end process;
end architecture behavioral;
Here with the process sensitivity list supplied with the longest static prefix.
This code will analyze (compile) successfully.
In VHDL and other hardware languages, it is my understanding that all conditions from true logic in a process happen at the same time. I have a std_logic FLAG variable that appears to me to have a conflict. I saw this code in a publication and I do not understand it. It looks like the FLAG variable can be assigned two values. Is this bad code or am I missing something? (The Process has some input triggers but no CLK.)
The variable names were changed to protect the innocent.
...
process(op_state, ...)
begin
FLAG <= '0';
case op_state is
when STATE_SLEEP =>
FLAG <= '1';
when some other cases not containing FLAG
end case;
end process;
I am going to assume both assignments are in the same process.
That coding style is allowed. If there are multiple assignment in a process the LAST one 'wins' from the previous one. This is even on part of a vector.
I often use this to set a default:
-- Default set all read bits to zero
axil_rdata<= (others => '0');
case (radrs) is
when X"00" => axil_rdata( 7 downto 0) <= control;
when X"04" => axil_rdata(15 downto 0) <= status;
when X"08" => axil_rdata <= counter;
...
Thus all bits of axil_rdata are first set to zero. Then some bits get assigned a new value.
I am new to vhdl and I have a question that I could not find an answer to.
I am trying to implement some algorithm that operates on a vector 1024 bits long. So I have to read data from a file and insert them in this temp_vector(1023 downto 0).
The file contains many inputs and for each one the algorithm operates on the output of the previous one. The problem is that the length of this input data is not constant, but each input length varies from 0 to 16000.
In each cycle I can only read 64 bits from my testbench and insert them. At specific moments I also have to append sequences of bits of variable length to the already inserted data. I use the integer bit_position to keep track of the last position of temp_vector I inserted data in, and the integer data_in_length to tell me the actual length of the data that I read in each cycle.
After temp_vector is full or I finished inserting all the input, I stop reading and the algorithm operates on temp_vector and then the reading from the file resumes.
I get correct results in simulations. The problem I have is with FPGA and ASIC synthesis. It has to do with the varying length of the input data.
I came up with two approaches in order to read the file and insert the data to temp_vector.
First
temp_vector_proc : process(clk, rst_n)
begin
if rst_n = '0' then
state <= RESET;
elsif clk'event and clk = '1' then
case state is
when RESET =>
state <= TAKING_DATA;
enable_calculations <= '0';
bit_position <= 0;
temp_vector <= (others => '0');
when TAKING_DATA =>
if take_data = '1' then
for i in 0 to 63 loop
temp_vector(i+bit_position) <= data_in_keyak(i);
end loop;
bit_position <= bit_position +data_in_length;
end if;
when ...
.....
end case;
end if; -- end rst_n = '0'
end process temp_vector_proc;
And second
when TAKING_DATA =>
if take_data = '1' then
temp_vector(63+ bit_position downto bit_position) <= data_in(63 downto 0);
bit_position <= bit_position +data_in_length;
end if;
when ...
.....
end case;
The second approach is working in FPGA but it is taking a lot of time and consuming too many Logic Elements and for design compiler it is returning an error that the range has to be constant.
The first one is also working in FPGA and returning no error in ASIC ( Design compiler), but for the ASIC it runs forever (I let it run overnight). It was stuck at beginning Pass 1 Mapping of the entity that contains the first code.
I hope I explained my problem enough and I would really appreciate some thoughts on how to implement it in a more efficient way.
I do not think I can go with generics because the file is read and operated on in one go, so the lengths are changing during the simulation. I also though about shifting but since the shifting value would be changing each time, i guess that it would still consume a lot of time/area.
Finally could my whole approach be wrong? I mean is it possible that for FPGA and especially for ASIC I need to be working on specific input sizes? That would mean that I should try to write and synthesize code that does not work for all of my file, but for some of its inputs with some specified size only.
Thanks a lot in advance for your time.
I'm working on the implementation of a FIR filter in VHDL and need some advice regarding when to use and not to use process statements. Part of the code is presented below. Specifically, I'm wodering how the resetCoeffs loop will synthesize. Will it be a sequential reset, and so be very inefficeint in both speed and area I assume, or will it be done in parallel? If the former is the case, how would I go about writing it so that is can be a parallel reset.
process (clk) is begin
if rising_edge(clk) then
if rst = '1' then
-- Reset pointer
ptr <= (others => '0');
-- Reset coefficients
resetCoeffs: for i in 0 to ORDER - 1 loop
coeffs(i) <= (others => '0');
end loop;
else
-- Increment pointer
ptr <= ptr + 1;
-- Fetch input value
vals( to_integer(ptr) ) <= ival;
-- Write coefficient
if coeff_wen = '1' then
coeffs( to_integer(ptr) ) <= ival;
end if;
end if;
end if;
end process;
It's going to be parallel. It basically has to be since the whole loop (everything in the process, really) has to operate in a single clock cycle in hardware.
I'm curious, though. Since you've made the effort to write out the whole process, why not just synthesize it with your favorite synthesizer? That's what I did, to check my answer.
Once a process begin execution (because of a change in one of the signals in its sensitivity list) it must run until it suspends, either by reaching the end, or reaching a wait statement.
Because of this defined behaviour, loops will "execute" all their code until they exit before time is allowed to move on in the simulator. The synthesiser will therefore create the same behaviour by unrolling all the loop and making sure it "all happens at once" (or at least within the clock tick for a clocked process like yours).