I am having trouble understanding why my code have a latch
logic [1:0] lru_list [0:3];
always_comb begin
if(reset) begin
lru_list[0] = 0;
lru_list[1] = 0;
lru_list[2] = 0;
lru_list[3] = 0;
end
else begin
case({access, update, access_index_i < 4})
3'b101: begin
lru_list[0] = lru_list[0] + 1;
lru_list[1] = lru_list[1] + 1;
lru_list[2] = lru_list[2] + 1;
lru_list[3] = lru_list[3] + 1;
lru_list[access_index_i] = 0;
end
3'b011: begin
lru_list[0] = lru_list[0];
lru_list[1] = lru_list[1];
lru_list[2] = lru_list[2];
lru_list[3] = lru_list[3];
lru_list[access_index_i] = 0;
end
default: begin
lru_list[0] = lru_list[0];
lru_list[1] = lru_list[1];
lru_list[2] = lru_list[2];
lru_list[3] = lru_list[3];
end
endcase
end
end // always_comb
In the case statement, I have a default case which will catch all the unmatched values. I have also set each index in the array a value. I don't understand where I am implicitly setting my array a implicit value.
I thought it might have to do with lru_list[access_index_i] = 0;, but commenting those two lines out will still give me the save error.
Here is what I would start with.
First add a sensitivity list to the always statement. You have a "reset" if in there so it sounds like you want the always # (posedge clk or posedge reset). I know you are using always_comb, but I would be curious to know if that actually does remove the issue or not. It would be telling.
EDIT: So I just realized you are doing operations on the LHS variables using the same variables on the RHS. You need to clock this. Otherwise when you combinatorially enter the counting state, it can never resolve as it is always adding in an infinite loop. Do the always # (posedge clk or posedge reset) and you will get better results I think.
Second, and probably more important, it looks like you are using access_index_i < 4 and trying to extract a bit from it to make up the least significant bit of your concatenated vector {access, update, access_index_i < 4}. If you are shifting to the right, I think the logic would insert 4'b0000 in the result and I am guessing it is not really a bit to begin with, so I am wondering what bit actually gets used during the 3'b101 case as it would be addressed by {bit,bit,vector}. Seems like you would want to say {bit,bit,vector[4]} or something to that effect. You might actually be using the least significant 3 bits of the your access_index_i to address your combinational statement.
EDIT: Responding to your comment below. You can, (And this is what I do) break the problem into two parts, the combinatorial and the clocked.
reg [3:0] my_sig;
wire [3:0] my_sig_wire;
always # (posedge clk)
begin
my_sig <= my_sig_wire;
end
always (*)
begin
if(reset)
begin
my_sig_wire = 4'b0000; // This will also reset the clocked version
end
else
begin
my_sig_wire = my_sig; // This is okay, because no matter
// how much I alter my_sig_wire, my_sig will
// only change on the clock pulse. So
// we avoid the infinite loop problem
my_sig_wire[index] = 1'b0; // Tweak one of the signals for fun.
// on the next clock, my_sig is updated!
end
end
Combinatorial blocks define there output purely based on inputs, there is no state.
Sequential elements (flip-flops) contain state and therefore outputs can be based on inputs and state, or just state.
Your default statement:
default: begin
lru_list[0] = lru_list[0];
Is maintaining state by holding a value and therefore can not be combinatorial. You have not defined a flip-flop (#(posedge clk)) so a latch has been inferred to hold the state.
Related
I have a problem with Pascal, especially Lazarus.
First of all, I created two random arrays of integer:
procedure TForm1.b_arraycreate1Click(Sender: TObject);
begin
randomize;
for i := 1 to 5 do
arr1[i] := random(10);
end;
And
procedure TForm1.b_arraycreate2Click(Sender: TObject);
begin
randomize;
for j := 1 to 5 do
arr2[j] := random(10);
end;
I know, I could put it in one procedure as well but doesn't matter now.
I want to compare these two. I wrote the following code:
procedure TForm1.b_comparisonClick(Sender: TObject);
var v:boolean;
begin
for i := 1 to 5 do begin
for j := 1 to 5 do begin
if arr1[i] = arr2[j]
then
begin
v:=true;
end
else
begin
v:=false;
end;
end;
end;
if v = true
then
begin
ShowMessage('Yes, there is a similarity! You can find number ' +IntToStr(arr1[i])+ ' in array 1, position ' +IntToStr(i)+ ' and also in array 2, position ' +IntToStr(j)+ '.');
end
else
begin
ShowMessage('No similarities... Generate new ones!');
end
end;
In my own words: I want to push a button and then there should be a message window with the information if there is one number (for example 7) which exists in array 1 and array 2. If yes, it should also write the position (index) of this number.
Unfortunately, this program doesn't work and I don't know why. It always shows "No similarities" (and don't worry about the creation of the arrays. I also have a label where I can test the content of the arrays every time).
Is there a (silly) mistake in my code here?
As explained already by MartynA in his comment, your algorithm is wrong. Your words are:
if there is one number which exists in array 1 and array 2
To see if it is so, you must scan all array1 and, for each number, see if it exists somewhere in array2.
So yes, you need two cycles, one nested in the other. As soon as you find a correspondence, you must stop. Or, if you want more results (find multiple duplicates), show a message instead of stopping - and go ahead. Third possibility (more complicated): when found, store the couple of indexes (without overwrite old results...) and go ahead. I will only show the first option:
procedure TForm1.b_comparisonClick(Sender: TObject);
var
i,j: integer;
v: boolean;
begin
v := false;
for i := 1 to 5 do begin
for j := 1 to 5 do begin
if arr1[i] = arr2[j] then begin
v := true;
break
end
end // inner, j
end; // outer, i
if v = true
then ShowMessage(.....)
else ShowMessage('No similarities...');
end; // proc comparison
I tried to respect your code a bit, there are a few possible "shortcuts"; for example, if v is a boolean variable, it is better to write if v then instead of if v=true then, and some others, like
v := arr1[i]=arr[j];
...or... the outer loop does not need begin+end.
******* BEWARE (see comment below about break)
To stop/exit from two nested cycle is not so simple... perhaps a goto... the code above works, but the break does little work.
******* second update, as described by comment below. IT DOES NOT WORK, because if the break does not exit BOTH loops, the outer index gets modified. The correct cycle using TWO breaks is as follows:
for i := 1 to 5 do begin
for j := 1 to 5 do begin
if arr1[i] = arr2[j] then begin
v := true;
break
end
end; // inner, j
if v then break
end; // outer, i
Sorry for the mistakes... :-)
I would prefer a GOTO to exit both loops: it is faster, single instruction, and more clear ("goto found" instead of a generic break). But GOTOs are not very popular... so I've been afraid!
I would like to write a module that uses some coefficients that are loaded from a file.
For example:
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
coeffs[0] <= 3;
coeffs[1] <= 2;
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
I would like to replace the values 3 and 2 by values that I can modify in a file, and provide the file during synthesis.
Obviously, this file will only assign initial values to the registers.
I don't want it to be a block ram, I want it to be like independent registers.
Just to clarify, I need the solution to be very generic, because I intent to use it in many modules that are doing the same thing, but with a different number of coefficients.
Meaning, in the end I wish to have a generic module that receives as a parameter a file name that stores the coefficients, and the number of coefficients and their width, and generates a code using those parameters.
I have tried readmemh but I understood it is only synthesizable to initiate a memory.
Any suggestions?
Thanks.
Here's a suggestion: put the statements initialising the array coeffs in an include file, eg
coeffs.v:
coeffs[0] <= 3;
coeffs[1] <= 2;
code:
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
`include "coeffs.v"
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
An include file is included at compile time. So, your synthesiser will insert the contents of the file in the right place in the design. You could then manage the files using your operating system.
I am happy to stand corrected, but apart from 'Trickery' (Include files, define files, running a script generating such before synthesis) I am not aware of any method where you can load plain numbers from a file for synthesis.
I admit it a is problem waiting for a solution.
If only to prevent major embarrassment when your chip comes back from the manufacturer and you find the boot-rom is completely empty.... As if that ever happened where I worked (rolls eyes) Fixing requires only a single (contact) layer change but the lower layer masks are the most expensive).
Using parameter to pass the initial value is better option.
module A
#( parameter INITIAL_VALUE_COEFFS_0 = 3,
parameter INITIAL_VALUE_COEFFS_1 = 2)
( /* ignore it */ );
reg [3:0] coeffs[0:1];
reg [6:0] ans;
always #(posedge clk) begin
if (!reset) begin
coeffs[0] <= INITIAL_VALUE_COEFFS_0;
coeffs[1] <= INITIAL_VALUE_COEFFS_1;
ans <= 0;
end
else begin
ans <= coeffs[0] * coeffs[1];
end
end
endmodule
basically I have a array of unsigneds and a process that increments the first value of in the array by one. This worked fine untill I implemented an asynchronos reset, that sets the elements of the array to 0. The weird thing is, even when the code of the asynchronos reset is never reached, it makes the rest of my code not work anymore. Here is my code:
use work.datentyp.all;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity vektoruhr is
port (
clk, reset : in std_logic ;
);
end vektoruhr;
architecture v1 of vektoruhr is
signal internal_stamp : vektor := (others => (others => '0'));
begin
process(clk)
begin
if(rising_edge(clk)) then
internal_stamp(0) <= internal_stamp(0) + 1;
end if;
end process;
process(reset)
begin
if(rising_edge(reset)) then
report "reset triggered";
-- internal_stamp <= (others => (others => '0'));
alarm <= '0';
end if;
end process;
end v1;
As you can see, the line
-- internal_stamp <= (others => (others => '0'));
is commented out. Like this, everything works fine. But if I delete the --, the value of the first element is 00 first, then gets changed to 0x after the first incrementation and to xx after the second one. After that it stay at xx. The reset input is set to '0' from the begining and is never changed.
VHDL is a hardware description language. Each process represents a piece of hardware. You are driving the signal internal_stamp from two processes.; you have a short circuit. When you comment out the line
internal_stamp <= (others => (others => '0'));
this results in internal_stamp being driven from only one process. Hence no short circuit and no 'X' values.
If you're coding sequential logic, you should stick to a template. Here is one such template for sequential logic with an asynchronous reset, which all synthesis tools should understand:
process(clock, async_reset) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if async_reset ='1' then -- or '0' for an active low reset
-- set/reset the flip-flops here
-- ie drive the signals to their initial values
elsif rising_edge(clock) then -- or falling_edge(clock)
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
Here is a template for sequential logic without an asynchronous reset:
process(clock) -- nothing else should go in the sensitivity list
begin
if rising_edge(clock) then -- or falling_edge(clock)
-- put the synchronous stuff here (including the reset)
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
So, you should code your logic using one process, not two. Assuming you want an asynchronous reset:
process(clk, reset)
begin
if reset = '1' then
report "reset triggered";
internal_stamp <= (others => (others => '0'));
alarm <= '0';
elsif(rising_edge(clk)) then
internal_stamp(0) <= internal_stamp(0) + 1;
end if;
end process;
However, if you want a synchronous reset:
process(clk)
begin
if(rising_edge(clk)) then
if reset = '1' then
report "reset triggered";
internal_stamp <= (others => (others => '0'));
alarm <= '0';
else
internal_stamp(0) <= internal_stamp(0) + 1;
end if;
end process;
The following is code I wrote is a test bench to simulate a decoder (Verilog HDL). It converts [15:0]IR to [25:0]ControlWord. Literal is a byproduct that is watched as well.
All values from 0-65535 need to be tested for the 16-bit IR variable. In the beginning of the loop, I distinctly assign IR to be 0, but Quartus is telling me that:
Warning (10855): Verilog HDL warning at controluni_tb.v(20): initial value for variable IR should be constant
and as a result I get the following:
Error (10119): Verilog HDL Loop Statement error at controluni_tb.v(23): loop with non-constant loop condition must terminate within 250 iterations
The code for my test bench module is as follows:
module controluni_tb;
reg [15:0]IR;
reg clock;
wire [25:0]ControlWord;
wire [15:0] literal;
Total_Control_Unit_2 dut (IR,ControlWord,literal);
initial
begin
clock <= 1'b0;
end
initial
begin
IR <= 16'b0;
end
initial
begin
forever
begin
#1 IR <= IR + 16'b1;
end
end
initial
#65535 $finish;
endmodule
Your code has no errors. initial blocks and system functions ($finish) is used for simulation (not synthesis). That error is related to synthesis. I edited your code for more readability (your clock is always zero!) :
module controluni_tb;
reg [15:0]IR;
reg clock;
wire [25:0]ControlWord;
wire [15:0] literal;
Total_Control_Unit_2 dut (IR,ControlWord,literal);
initial begin
clock = 1'b0;
end
initial begin
IR = 16'b0;
forever #1 IR = IR + 16'b1;
end
initial begin
#65535 $finish;
end
endmodule
Instead of using a forever loop, why not just use a for loop for IR? Then the problem is completely bounded.
initial begin
for (IR = 0; IR <= 65535; IR++);
$finish;
end
I am trying to do the following : concat = {concat[7:0],clk} inside a forever loop as below :
bit [7:0] concat;
concat = 0;
forever begin
#(posedge clk);
concat = {concat[7:0],clk};
end
I wanted to know what value will it contain after 8 clock iterations at any point of time, if the initial value of concat = 0.
Can it be different from 'hAA or 'h55 at any point of time?
You can not just write concat = 0; you should either assign concat = 0; or
initial begin
concat = 0;
end
Forever can not be used like that, the only two top levels you're allowed are initial and always. You want some thing like the following for a simulation:
initial begin
forever begin
#(posedge clk);
concat = {concat[6:0],clk};
end
end
If you are writing for synthesis then you might want to imply a flip-flop:
always #(posedge clk) begin
concat = {concat[6:0],clk};
end
Once you have fixed your RTL it should be easy to try out on EDA Playground.
Since you have #(posdege clk), clk will always be 1 (or x) when evaluating the RHS of the assignment. So concat will be 'h00, 'h01, 'h03, 'h07, 'h17, ...
Also note that if any other thread tries to read concat on the same positive edge of clk, you have a race condition, so please use a NBA to make the assignment.