If I write the statement to assign a to be a+1 in a VHDL process, is it a good practice?
I am confused about this because the simulator works fine, but when I try to implement it in FPGA the synthesis tool complains about creating latches.
What does this mean?
you should do such a statement only in a clocked process. if you want to have it synthesised, an additional initialisation (reset) is suggested. might look as follows:
process(clk, reset)
begin
if reset='1' then
a <= 0;
elsif rising_edge(clk) then
a <= a + 1;
end if;
end process;
In a clocked process, this is fine. Anywhere else, probably not.
Do it in a clocked process, that's fine. What it means is "the next value of a should be the current value of a +1"
If you do it as a continuous assignment (outside of any process), what you are saying is "a is always getting a+1 assigned to it" which is a self-referential loop!
If you include a in the sensitivity list of an enabled process, you get the same effect
process (en, a)
begin
if en = '1' then
a <= a + 1;
end if;
end process;
(You can use this form to create transparent latches:
process (en, insig)
begin
if en = '1' then
a <= insig;
end if;
end process;
)
If you do it in a non-clocked process, which is not sensitive to a:
process (en)
begin
if en = '1' then
a <= a + 1;
end if;
end process;
You will create a positive-edge-triggered latch, as a needs to keep its value between changes of en. Effectively, en becomes a clock to a d-type flipflop.
Related
I have this simple code checked with Quartus II. First, It gives me error 5000 iterations for loop limit then I try to change verilog constant loop limit variable in settings and now it is giving me this error
Error (293007): Current module quartus_map ended unexpectedly. Verify that you have sufficient memory available to compile your design. You can view disk space and physical RAM requirements on the System and Software Requirements page of the Intel FPGA website (http://dl.altera.com/requirements/).
Is this something related to tool limitation or am I doing something wrong with my code ?
Here is my code:
module Branch_status_table #(parameter BST_length = 16383) //16383
(
output reg [2:1] status,
output reg [32:1] PC_predict_o,
input wire [2:1] status_update,
input wire [32:1] PC_in, PC_update,
input wire [32:1] PC_predict_update,
input wire clk,en_1,RST
);
wire [14:1] PC_index, PC_index_update;
//Internal memory
reg [2:1] status_bits [BST_length:0];
reg [32:1] PC_predict [BST_length:0];
reg [16:1] PC [BST_length:0];
//Combinational
assign PC_index = PC_in [16:3];
assign PC_index_update = PC_update [16:3];
//
initial begin
for ( int i=0; i <= BST_length; i=i+1) begin
status_bits[i] <= 0;
PC_predict[i] <= 0;
PC[i]<=0;
end
end
//Prediction
always_ff #(posedge clk) begin
if ( (PC[PC_index]==PC_in[32:17]) && (status_bits[PC_index]!=0) ) begin
status <= status_bits [PC_index];
PC_predict_o <= PC_predict [PC_index];
end
else begin
status <= 0;
PC_predict_o <= 0;
end
end
//Update
always_ff #(posedge clk) begin
if (en_1==1) begin
status_bits[PC_index_update] <= status_update;
PC [PC_index_update] <= PC_update[32:17] ;
PC_predict[PC_index_update] <= PC_predict_update;
end
else begin
status_bits[PC_index_update] <= status_bits[PC_index_update] ;
PC [PC_index_update] <= PC [PC_index_update] ;
PC_predict[PC_index_update] <= PC_predict[PC_index_update] ;
end
end
endmodule
There a coding issue and maybe a resource utilization issue.
The coding issue:
The code infers block ram, and is attempting initialize/reset it.
In general you can't reset block rams using a single initial block.
That style of initialization of arrays can be done in a testbench, not in RTL.
Synthesis tools have physical limits.
To reset/initialize a block ram you must write 0 to each address. Use the same type of synchronous process (always #(posedge clk)) because the memory is a synchronous device. Put a mux in front of the write port and use a state machine a start up to write 0's to every address, then when the state machine finishes the state that move to an state where the BRAM behaves like you normally want it to.
This page discusses the issue.
https://www.edaboard.com/threads/how-to-clear-reset-my-bram-in-vhdl-xilinx.247572/
This is a Xilinx related answer; other vendors work the same way.
Summarizing the coding issue: You probably don't need to initialize and you can't do it this way:
initial begin
for ( int i=0; i <= BST_length; i=i+1) begin
status_bits[i] <= 0;
PC_predict[i] <= 0;
PC[i]<=0;
end
end
Potential Utilization Issue:
FPGAs' have finite resources.
The tool seems to be indicating that the code infers more block ram than the part has. To verify this, change parameter BST_length from 16K to something small like 8 and see if the utilization issue ("insufficient memory") goes away. If it goes away then re-design using less memory.
This can also be analyzed by hand knowing how much BRAM the part has and how much you are inferring. Don't infer more than the part has.
The tool is giving different answers with simple code changes because of two issues related to the same inference of BRAM. When the code changes a little the tool switches and informs about the other issue. This is how the tools work sometimes, a first error can mask a second by erroring out so that the 2nd error is not reached.
Can anyone help me in writing VHDL code for bubble sort given an array of data as input?
I have declared in_array as input which contains 15 array elements. i want to bubble sort them in descending order.
in_array is input array.
sorted_array is out put array.
in_array_sig is signal of type in_array
I am facing problem with statements inside process
Below is my code:
architecture behav of Bubblesort is
signal in_array_sig : bubble;
signal temp : std_logic_vector(3 downto 0);
signal i : integer := 0;
begin
in_array_sig <= in_array;
proc1 : process(clk, reset)
begin
if reset = '0' then
if (clk'event and clk = '1') then
while (i <= 15) loop
if (in_array_sig(i) < in_array_sig(i + 1)) then
temp <= in_array_sig(i);
in_array_sig(i) <= in_array_sig(i + 1);
in_array_sig(i + 1) <= temp;
end if;
i <= i + 1;
end loop;
end if;
end if;
end process;
sorted_array <= in_array_sig;
end behav;
I am beginner in VHDL coding. Kindly help me with this.
The lack of a Minimal Complete and Verifiable example makes it hard to provide an answer about all the the things stopping your code from bubble sorting accurately. These can be described in the order you'd encounter them troubleshooting.
proc1 : process(clk, reset)
begin
if reset = '0' then
if (clk'event and clk = '1') then
while (i <= 15) loop
if (in_array_sig(i) < in_array_sig(i + 1)) then
temp <= in_array_sig(i);
in_array_sig(i) <= in_array_sig(i + 1);
in_array_sig(i + 1) <= temp;
end if;
i <= i + 1;
end loop;
end if;
end if;
end process;
Before starting note that the clock is gated with reset. You could qualify assignments with reset making it an enable instead.
Problems
The first thing we'd find producing an MCVe and a testbench is that the process never suspends. This is caused by the condition in the while loop depending on i and i a signal being updated within the process. i shouldn't be a signal here (and alternatively you could use a for loop here).
This also points out that temp is a signal and suffers the same problem, you can't use the 'new' value of temp until the process has suspended and resumed. Signals are scheduled for update, a signal assignment without a waveform element containing an after clause have an implicit after clause with zero delay. Signal updates do no occur while any process scheduled to resume has yet to resume and subsequently suspend. This allows the semblance of concurrency for signals who's assignments are found in sequential statements (a concurrent statement has an equivalent process containing equivalent sequential statements). So neither i nor temp can update during execution of a processes sequence of statements and both want to be variables.
We'd also get bitten using a signal for in_array_sig. As you increment i the previously indexed in_array_sig(i + 1) becomes the next loop iteration's in_array_sig(i). Without an intervening process suspend and resume the original value is available. in_array_sig wants to be a variable as well.
If we were to fix all these we'd also likely note that i is not initialized (this would be taken care of in a for loop iteration scheme) and we might also find that we get a bound error in a line using an (i + 1) index for in_array_sig. It's not clear without the author of the question providing an MCVe whether the array size is 16 (numbered 0 to 15) or 17. If the former i = 15 + 1 would be out of the index range for the undisclosed array type for in_array, in_array_sig, and sorted_array.
If we were to insure the index range is met noting that we only need 1 fewer tests and swaps than the number of elements in an array we'd find that what the process isn't a complete bubble sort. We would see the largest binary value of in_array_sig end up as the right most element of sorted_array. However the order of the remaining elements isn't guaranteed.
To perform a complete bubble sort we need another loop nesting the first one. Also the now 'inner' for loop can have a decreasing number of elements to traverse because each iteration leaves a largest remaining element rightmost until the order is assured to be complete.
Fixes
Fixing the above would give us something that looks like this:
architecture foo of bubblesort is
use ieee.numeric_std.all;
begin
BSORT:
process (clk)
variable temp: std_logic_vector (3 downto 0);
variable var_array: bubble;
begin
var_array := in_array;
if rising_edge(clk) then
for j in bubble'LEFT to bubble'RIGHT - 1 loop
for i in bubble'LEFT to bubble'RIGHT - 1 - j loop
if unsigned(var_array(i)) > unsigned(var_array(i + 1)) then
temp := var_array(i);
var_array(i) := var_array(i + 1);
var_array(i + 1) := temp;
end if;
end loop;
end loop;
sorted_array <= var_array;
end if;
end process;
end architecture foo;
Note the loop iteration schemes are described in terms of type bubble bounds, the outer is one shorter than the length and the inner is one shorter for each iteration. Also note the sorted_array assignment is moved into the process where the in_array_sig variable replacement var_array is visible.
Also of note is the use of the unsigned greater than operator. The ">" for std_logic_vector allows meta-values and 'H' and 'L' values to distort relational comparison while the operator for unsigned is arithmetic.
Results
Throw in package and entity declarations:
library ieee;
use ieee.std_logic_1164.all;
package array_type is
type bubble is array (0 to 15) of std_logic_vector(3 downto 0);
end package;
library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;
entity bubblesort is
port (
signal clk: in std_logic;
signal reset: in std_logic;
signal in_array: in bubble;
signal sorted_array: out bubble
);
end entity;
along with a testbench:
library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;
entity bubblesort_tb is
end entity;
architecture fum of bubblesort_tb is
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal in_array: bubble :=
(x"F", x"E", x"D", x"C", x"B", x"A", x"9", x"8",
x"7", x"6", x"5", x"4", x"3", x"2", x"1", x"0");
signal sorted_array: bubble;
begin
DUT:
entity work.bubblesort(foo)
port map (
clk => clk,
reset => reset,
in_array => in_array,
sorted_array => sorted_array
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if now > 30 ns then
wait;
end if;
end process;
end architecture;
and we get:
something that works.
The reset as enable has not been included in process BSORT in architecture and can be added in, inside the if statement with a clock edge condition.
And about here we get to Matthew Taylor's point in a comment about describing hardware.
Depending on the synthesis tool the process may or may not be realizable as hardware. If not you'd need intermediary variables holding the array portions used in each successive iteration of the inner loop.
There's also the issue of how much you can do in a clock cycle. Worst case there is a delay depth comprised of fifteen element comparisons and fifteen 2:2 selectors conditionally swapping element pairs.
If you were to pick a clock speed that was incompatible with the synthesized delay you'd need to re-architect the implementation from a software loop emulation to something operating across successive clocks.
That could be as simple as allowing more clock periods by using that enable to determine when the bubble sort is valid for loading into the sorted_array register. It could be more complex also allowing different and better performing sorting methods or a modification to bubble sort to say detect no more swaps can be necessary.
I do have following VHDL code snipped:
signal state_last_pushbutton : std_logic;
process (clk_clk)
begin
if rising_edge(clk_clk) then
userleds_external_connection_export(0) <= '0';
else
userleds_external_connection_export(0) <= '1';
end if;
state_last_pushbutton <= pushbuttons_external_connection_export(0);
end process;
Question:
Why the signal state_last_pushbutton never gets the value of pushbuttons_external_connection_export(0)? In the simulation its value remains always 'U'.
Thanks
It seems like you are trying to write a clocked process, in which case you should probably write something like this:
signal state_last_pushbutton : std_logic;
process (clk_clk)
begin
if rising_edge(clk_clk) then
state_last_pushbutton <= pushbuttons_external_connection_export(0);
end if;
end process;
This will update state_last_pushbutton to the value stored in the register or signal pushbuttons_external_connection_export(0) on each rising edge of the clock.
Have you checked that pushbuttons_external_connection_export(0) is actually set to some known value, and that your clock is running properly?
I'm coming from a Verilog-95 background, and I'm trying to figure out what Verilog-95 hoops I don't have to jump through anymore.
The obvious way to write a flip flop with async set and reset in Verilog-95 is:
always #(posedge clk or negedge resetb or negedge setb) begin
if (!resetb) q <= 0;
else if (!setb) q <= 1;
else q <= d;
end
This works in synthesis. But, this doesn't work in simulation if we ever assert both resetb and setb, and then de-assert resetb before de-asserting setb, since there's no posedge trigger for either of those signals. We need to add the following (which varies depending on your synthesis tool), to get simulation to match synthesis:
// synopsys translate_off
always #(resetb or setb)
if (resetb && !setb) force q = 1;
else release q;
// synopsys translate_on
Is there a SystemVerilog construct that will let you do this without this extra junk? Better yet, is there a straightforward way to do it in Verilog-95?
Flip-flops with multiple asynchronous controls are best avoided. The timing checks necessary to ensure they function properly are complex and easy to mess up. If you really need to use them, then it's probably best to instantiate them by hand where needed. If you let your synthesis tool infer them, it may use them in places you don't intend, which increases the risk that the timing checks don't get done properly.
One final aside, there is a similar simulation-synthesis mismatch issue with all asynchronous flops, if the active edge of reset is at time zero and is simulated before the flop is initialized to x, and the clock isn't running in reset. I believe some simulators have special cases to ensure the logic is not initialized in this order.
That said, I had luck moving the priority logic outside the sequential always block. Note I'm using active-high signals for simplicity.
assign s_int = s && !c;
always #(posedge clk or posedge s_int or posedge c) begin
if (c)
q <= 1'b0;
else if (s_int)
q <= 1'b1;
else
q <= d;
end
This is something I wish SystemVerilog had improved. If you want to allow both being low at the same time, then stick with the current method.
The other option is to create a design rule stating the asynchronous signals can not be active at the same time and enforce the rule with an assertion. Assertions are suppose to be ignored by synthesizers, so translate_off/on should not be be necessary.
Here is an example using an inline assertion:
always_ff #(posedge clk, negedge resetb, negedge setb) begin : dff_asyncRbSb
if (!resetb) q <= 0;
else if (!setb) q <= 1;
else q <= d;
asrt_setrst : assert(resetb||setb)
else $error("resetb and setb can not be low at the same time.");
end : dff_asyncRbSb
I don't know any SV, so this isn't an answer, but the issue here is that
Verilog (and, I think, SV) event expressions are basically broken. The problem
is that, when you have multiple conditions in an event expression:
event_expression ::=
expression
| hierarchical_identifier
| posedge expression
| negedge expression
| event_expression or event_expression
| event_expression , event_expression
then there's no bullet-proof way to determine which expression caused the
event, since the only thing you can do is to check the current state of the
expression. So, if you've got #(posedge clk, posedge rst), for example, you
look at the current levels of clk and rst and hope this is sufficient to do
the job. In general, it isn't, but your example is the only practical case (I
think) that causes a problem.
VHDL handles this by having signal attributes, which let you determine whether
a signal has caused an event. In VHDL, you get an event when any signal in
your sensitivity list changes, and you then check their 'event attribute to
determine whether they fired the process. No confusion, no posedge or negedge,
and it all works.
I've just had a quick look at the SV LRM, and SV attributes appear to be the
same as Verilog attributes, so I think you're out of luck.
with no edge defined, the assertion and de-assertion of reset and set signals should be able to trigger this code in simulation.
always_ff should be able to create a flop at synthesis.
Below code is compilation clean using synopsys VCS tool.
always_ff #(posedge clk, resetb, setb) begin
if (!resetb) q <= 0;
else if (!setb) q <= 1;
else q <= d;
end
Try this:
always_ff #(posedge clk or negedge resetb or negedge setb)
systemverilog uses always_ff for clock triggered logic and always_comb for combo logic
I have an address counter in a VHDL sequential process. Its idle value is set in a configuration register to a certain max value; afterwards, anytime it enters a certain state it should increment by one.
To get the maximum value, I declare a subset of an input std_logic_vector as an alias.
I declared address_int as an unsigned variable. I then defined a sequential process with a clk and a reset in the sensitivity list. When the reset is asserted, the address counter is set to the alias value. After reset is released, the counter is rolled over/incremented on rising edges when in a certain state.
The synthesis tool gives me this message:
*WARNING:Xst:819 line 134: The following signals are missing in the process sensitivity list: DL_CADU_SIZE*
And all the address lines have become asynchronous signals! What is going on here? Is there some strange behavior with unsigned that doesn't occur with integers? I usually use integers here, but the conversion seemed more straightforward from unsigned for purposes of code maintenance. I have tried ditching the alias and doing the straight conversion, but it didn't help.
library IEEE;
use ieee.std_logic_1164.a
use ieee.numeric_std.all;
-- entity declaration, ports, architecture, etc.
signal address_int : unsigned(8 downto 0);
alias aMaxWords : std_logic_vector(8 downto 0) is DL_CADU_SIZE(10 downto 2);
begin
WADDR <= std_logic_vector(address_int);
OUT_PROC: process (CLK_CORE, RST_N_CORE)
begin
if RST_N_CORE = '0' then
address_int <= unsigned(aMaxWords);
elsif rising_edge(CLK_CORE) then
if next_state = WRITE_WORD then
if address_int = unsigned(aMaxWords) then
address_int <= (others => '0');
else
address_int <= address_int + 1;
end if;
end if; -- WRITE_WORD
end if; -- rising_edge
end process OUT_PROC;
end RTL;
This:
if RST_N_CORE = '0' then
address_int <= unsigned(aMaxWords)
describes an async reset - therefore aMaxWords will be treated as asynchronous by the synthesiser irrespective of whether it is or not.
What the synthesiser interprets your code as is "while rst_n_core is low, copy the value of aMaxWords to address_int" so if aMaxWords changes during reset, the value must be copied across. The lack of that signal in your sensitivity list means that the synthesiser is making a circuit which behaves differently to what the language says it should, hence the warning.
It really shouldn't do this: without the signal in the sensitivity list, it ought to capture the signal on the falling edge of the reset line. But as that's not how most chips work, the synthesiser designers (in their infinite wisdom) decided many years ago to assume the designer intended to have that signal in the sensitivity list, and issue a warning, rather than saying "this can't work, fix it". So then you get code which works differently in simulation and synthesis. End rant.
Your reset code:
if RST_N_CORE = '0' then
address_int <= unsigned(aMaxWords);
is wrong. The definition of reset is set your circuit to known-state. But your code assign it to a signal. You should assign it as all 0 or all 1 for reset, or your aMaxWords must be constant (note that your synthesizer may be not enough intellegent for known it, then should assign it as constant) :
if RST_N_CORE = '0' then
address_int <= (others => '0');
or
if RST_N_CORE = '0' then
address_int <= (others => '1');