sequential equivalence with more than one multi bit register - yosys

extremely simple sequential logic equivalence test case:
module memory1(
input wire clk,
input wire srst,
input wire [15:0] addr,
input wire din,
input wire wr,
input wire rd,
output reg [15:0] out
);
reg [15:0] mem;
always_ff #(posedge clk) begin
if (srst) begin
mem <= 'd0;
out <= 'd0;
end
else begin
if (wr) mem[addr] <= din;
out <= mem;
end
end
endmodule
And then:
module memory2(
input wire clk,
input wire srst,
input wire [15:0] addr,
input wire din,
input wire wr,
input wire rd,
output reg [15:0] out
);
reg [15:0] mem;
always_ff #(posedge clk) begin
if (srst) begin
mem <= 'd0;
out <= 'd0;
end
else begin
if (wr) case (addr)
'd0 : mem[0] <= din;
'd1 : mem[1] <= din;
'd2 : mem[2] <= din;
'd3 : mem[3] <= din;
'd4 : mem[4] <= din;
'd5 : mem[5] <= din;
'd6 : mem[6] <= din;
'd7 : mem[7] <= din;
'd8 : mem[8] <= din;
'd9 : mem[9] <= din;
'd10 : mem[10] <= din;
'd11 : mem[11] <= din;
'd12 : mem[12] <= din;
'd13 : mem[13] <= din;
'd14 : mem[14] <= din;
'd15 : mem[15] <= din;
endcase
out <= mem;
end
end
endmodule
using the yosys script:
read_verilog -sv example_mem.sv
proc
memory
miter -equiv -flatten memory1 memory2 miter
hierarchy -top miter
sat -maxsteps 50 \
-set in_srst 0 -set-at 1 in_srst 1 \
-show-ports \
-seq 1 \
-tempinduct \
-prove trigger 0 \
miter
I can get an equivalence match, all is good.
However if I change both designs such that
out <= mem;
is replaced with:
else if (rd) out <= mem;
I get a non-equivalence.
however if I use the following method, I get a pass......
read_verilog -sv example_mem.sv
proc
memory
equiv_make memory1 memory2 equiv
hierarchy -top equiv
flatten
equiv_induct -seq 1
equiv_status -assert
Can anybody shed any light for me?
why does the miter method fail with the simple mod?

In temporal induction, this is essentially trying to prove that after starting in random states, assuming they are equal (with equal inputs) for N cycles, then they will always be equal at cycle N+1. When you add the read enable, there are paths through the design where state never "leaks" to the output so this technique no longer works.
A 50-cycle bounded model check (removing -tempinduct and -maxsteps, and setting -seq to 50), does pass as expected.
The second script passes because the equiv_ commands look into the design, and adds an extra check that the two mem registers are identical, which then allows induction to start off "synchronised" and pass.
This is in the context of assertion verification, rather than equivalence checking, but https://zipcpu.com/blog/2018/03/10/induction-exercise.html also discusses a similar problem with temporal induction.

Related

How to multiply two 1024-bit unsigned integers with very limited resources ( BASYS 2)

I will take two 1024-bit unsigned integers through serial communication ( 8-bit by 8-bit), convert ASCII to binary, then multiply them to form an output of 2048-bit. The main problem that I have to do multiplication operation with a very small-area FPGA board ( BASYS 2).
The multiplication speed is not an important criteria for me, I can wait a relatively long time ( ~ 1 sec ) to get the correct multiplication result.
Here is the resources information of my FPGA:
https://reference.digilentinc.com/_media/basys3:basys3_ss.pdf
What is a simple and area-effective way to do this?
a 1024-bit to 1024-bit adder takes alone around %53 of my area usage!
I assume you are certain that a true 1024 x 1024 multiplier really is needed (in many applications, something much cheaper will suffice). Maybe this is stating the obvious, but as a starting point I would try a very simple shift-add. Something like this would work (and I'm sure you can optimize it further to meet your needs):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity wide_mult is
generic (
A_BITS : positive := 1024;
B_BITS : positive := 1024
);
port (
clk : in std_logic;
-- Input
in_valid : in std_logic;
in_a : in unsigned(A_BITS-1 downto 0);
in_b : in unsigned(B_BITS-1 downto 0);
-- Output
out_valid : out std_logic;
out_prod : out unsigned(A_BITS+B_BITS-1 downto 0)
);
end wide_mult;
architecture rtl of wide_mult is
signal shifted_a : unsigned(A_BITS-1 downto 0);
signal shifted_b : unsigned(A_BITS+B_BITS-1 downto 0);
signal progress : std_logic_vector(A_BITS-1 downto 0);
signal sum : unsigned(A_BITS+B_BITS-1 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
-- Cycle 1
if in_valid = '1' then
-- Initialize
shifted_a <= in_a;
shifted_b <= resize(in_b, A_BITS+B_BITS);
progress <= std_logic_vector(to_unsigned(1, A_BITS));
else
-- Shift
shifted_a <= shift_right(shifted_a, 1);
shifted_b <= shift_left(shifted_b, 1);
progress <= progress(A_BITS-2 downto 0) & '0';
end if;
-- Cycle 2 - Accumulate sum
out_valid <= progress(A_BITS-1);
if progress(0) = '1' then
-- Init sum
if shifted_a(0) = '0' then
sum <= (others => '0');
else
sum <= shifted_b;
end if;
elsif shifted_a(0) = '1' then
-- Accumulate
sum <= sum + shifted_b;
end if;
end if;
end process;
out_prod <= sum;
end rtl;
Your device is very small. If the simple shift-add doesn't even get close to fitting, then this might indicate that you need to change your approach. Since you have an enormous amount of time to do this sum, then perhaps you could offload it to a nearby CPU?

Using variables from one entity into another in VHDL

I have a little question related to my VHDL code. I have to create a simulation for 1 bit of ALU. I created a D flip-flop and a Full Adder, and now I have to connect them with some simple logical gates. How can I do to use variables from this 2 entities to do this?
My code is:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY D_flipflop IS PORT (
D, Clock: IN STD_LOGIC;
Q: OUT STD_LOGIC);
END D_flipflop;
ARCHITECTURE Behavior OF D_flipflop IS
BEGIN
PROCESS(Clock)
BEGIN
IF Clock'EVENT AND Clock = '0' THEN
Q<= D;
END IF;
END PROCESS;
END Behavior;
ENTITY fa IS PORT (
Ci, Xi, Yi: IN STD_LOGIC ;
Ci1, Si: OUT STD_LOGIC) ;
END fa;
ARCHITECTURE Dataflow OF fa IS
BEGIN
Ci1 <= (Xi AND Yi) OR (Ci AND (Xi XOR Yi));
Si <= Xi XOR Yi XOR Ci;
End Dataflow ;

Iteration limit reached - simple counter in VHDL FSM

I'm having "Iteration limit reached" error in a simple FSM.
This is a part of of a bigger FSM I have to do for a class assignment, and I tracked the problem to this specific part.
The FSM will be controlling a counter, the state IDLE waits for inputs, ZERO sets the counter to zero, and the INCREMENT state increments the counter by one.
When simulating, the error occurs at the first time the input "inc" is high and the clock rises.
If I change the statement "temp := temp + 1;" for "temp := anything" the error stops. I really don't know what can be wrong, as for what I have found this error occurs when changing signals in the process sensitivity list inside the process itself.
I'm using Quartus II for the simulation.
Sorry for english mistakes.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.all;
entity fsm is
port
(
clock: in std_logic;
reset: in std_logic;
inc: in std_logic;
count: out std_logic_vector (13 downto 0);
cur_state: out std_logic_vector (1 downto 0)
);
end fsm;
architecture behaviour of fsm is
type state_type is (IDLE, INCREMENT, ZERO);
signal PS, NS: state_type;
begin
sync_proc: process (clock, reset)
begin
if (reset = '1') then
PS <= ZERO;
elsif (rising_edge(clock)) then
PS <= NS;
end if;
end process sync_proc;
comb_proc: process (PS, inc)
variable temp: unsigned (13 downto 0);
begin
case PS is
when IDLE =>
if (inc = '1') then
NS <= INCREMENT;
else
NS <= IDLE;
end if;
when INCREMENT =>
temp := temp + 1;
NS <= IDLE;
when ZERO =>
temp := "00000000000000";
NS <= IDLE;
when others =>
NS <= IDLE;
end case;
count <= std_logic_vector(temp);
end process comb_proc;
with PS select
cur_state <= "00" when IDLE,
"01" when INCREMENT,
"10" when ZERO,
"11" when others;
end behaviour;
You have a very serious CONCEPTUAL mistake in your case statement. Because it produces a combinational circuit (the combinational part of your FSM), it does not have memory, so it can't implement the equation "temp := temp + 1" (because, having no memory, it doesn't know what the value of temp is).
You can see more about this in chapter 11 of "Finite State Machines in Hardware...", by V.Pedroni, published by MIT.

VHDL testbench report error

working on a project with a self checking test bench and having a problem I do not understand.
The problem for the following code is an error in the simulation. I will point to where the error is coming from in the code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
ENTITY TestBenchAutomated IS
-- Generics passed in
generic (m: integer := 3; n: integer := 5; h: integer := 4; DATA_SIZE: integer :=5);
END TestBenchAutomated;
ARCHITECTURE behavior OF TestBenchAutomated IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT TopLevelM_M
generic (m: integer := 3; n: integer := 5; h: integer := 4; DATA_SIZE: integer :=5);
PORT(
clk : IN std_logic;
next_in : IN std_logic; --User input
rst_in : IN std_logic; --User input
OUTPUT : OUT SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0) --Calculated DATA output
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal next_in : std_logic := '0';
signal rst_in : std_logic := '0';
--Outputs
signal OUTPUT : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
--Variable to be used in assert section
type Vector is record
OUTPUT_test : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
end record;
type VectorArray is array (natural range <>) of Vector;
constant Vectors : VectorArray := (
-- Values to be compaired to calculated output
(OUTPUT_test =>"000000110000"), -- 48
(OUTPUT_test =>"000011110110"), -- 246
(OUTPUT_test =>"000101001000"), -- 382 <--- Purposefully incorrect value, Should be '000100001000' = 264
(OUTPUT_test =>"111111010011"), -- -45
(OUTPUT_test =>"111101001100"), -- -180
(OUTPUT_test =>"111111001111"), -- -49
(OUTPUT_test =>"000000101011"), -- 43 Purposefully incorrect value, Should be '000010101011' = 171
(OUTPUT_test =>"000000010011"), -- 19
(OUTPUT_test =>"111111100101"), -- -27
(OUTPUT_test =>"111110111011"), -- -69
(OUTPUT_test =>"111110111011"), -- -69
(OUTPUT_test =>"000000101101"), -- 45
(OUTPUT_test =>"111011011110"), -- -290
(OUTPUT_test =>"000001010110"), -- 86
(OUTPUT_test =>"000011110010"), -- 242
(OUTPUT_test =>"00000111110"), -- 125
(OUTPUT_test =>"111111001001"), -- -55
(OUTPUT_test =>"000100010101"), -- 277
(OUTPUT_test =>"111111100011"), -- -29
(OUTPUT_test =>"111101111101"));-- -131
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: TopLevelM_M PORT MAP (
clk => clk,
next_in => next_in,
rst_in => rst_in,
OUTPUT => OUTPUT
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Process to simulate user input and to check output is correct
Test :process
variable i : integer;
begin
wait for 100 ns;
rst_in <= '1';
wait for clk_period*3;
rst_in <= '0';
--Loops through enough times to cover matrix and more to show it freezes in S_Wait state
for i in 0 to 50 loop
for i in Vectors'range loop
next_in <= '1';
wait for clk_period*5;
next_in <= '0';
wait for clk_period*4; --Appropriate amount of clock cycles needed for calculations to be displayed at output
--Check the output is the same as expected
assert OUTPUT = Vectors(i).OUTPUT_test
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test))) --& lf &
--"But got" & integer'image(i)(to_integer(signed(OUTPUT)))
severity error;
end loop;
end loop;
wait;
end process;
END;
As you can see in the vector, I have inserted two incorrect values to make sure the code works. I there for expect an error in the simulation telling me that there is an error on address 2 of the vector and what integer it is. However, the simulation stops and i get this:
ERROR: Index 328 out of bound 1 to 1.
ERROR: In process TestBenchAutomated.vhd:Test
INFO: Simulator is stopped.
Obviously the integer 328 that is represented by the binary number in the vector causes this error, but I dont understand why it causes THIS error instead of the one I have coded. What is this index out of bound OF?
Any help would be much appreciated.
Thanks
This:
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
Should be:
report "Incorrect Output on vector line" & integer'image(i) &
lf & "Expected:" & integer'image(to_integer((Vectors(i).OUTPUT_test)))
It's complaining that the value (to_integer((Vectors(i).OUTPUT_test))) is out of range for a character when it should have been used as parameter to 'IMAGE, which you supplied already as i.
For a simplified test case:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
constant m: integer := 3;
constant n: integer := 5;
constant h: integer := 4;
constant DATA_SIZE: integer :=5;
end entity;
architecture fum of foo is
signal OUTPUT : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0) := "000011110110" ;
type Vector is record
OUTPUT_test : SIGNED((DATA_SIZE+DATA_SIZE)+(m-1)-1 downto 0);
end record;
type VectorArray is array (natural range <>) of Vector;
constant Vectors : VectorArray := (
-- Values to be compaired to calculated output
(OUTPUT_test =>"000011110110"), -- 246 (CORRECT)
(OUTPUT_test =>"000101001000") -- 382 (INCORRECT)
);
begin
TEST:
process
begin
for i in Vectors'RANGE loop
assert OUTPUT = Vectors(i).OUTPUT_test
report "Incorrect Output on vector line " & integer'image(i) &
-- lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
lf & "Expected:" & integer'image(to_integer((Vectors(i).OUTPUT_test)))
severity error;
end loop;
wait;
end process;
end architecture;
And the incorrect usage, Nick Gasson's nvc gave:
david_koontz#Macbook: nvc -a foo.vhdl
** Error: expected 2 parameters for attribute IMAGE but have 3
File foo.vhdl, Line 34
lf & "Expected:" & integer'image(i)(to_integer((Vectors(i).OUTPUT_t ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
With the correct number of arguments to `'IMAGE' (shown in the example):
david_koontz#Macbook: nvc -r foo
** Fatal: 0ms+0: Assertion Error: Incorrect Output on vector line 1
Expected:328
Process :foo:test
File foo.vhdl, Line 32
Found a ghdl bug not reporting this when it likely should. It worked either way (this should be a run time error). An integer value of 382 isn't a character eligible for concatenation.
Addendum:
Tristan Gingold (ghdl author) pointed out that the expression is an element index to the string output of the 'IMAGE function.
Further analysis reveals the basis for the error message on the original code for the question:
& integer'image(i)(to_integer((Vectors(i).OUTPUT_test)))
T'IMAGE(X)
Kind: Function.
Prefix: Any scalar type or subtype T.
Parameter: An expression whose type is the base type of T.
Result Type: Type String.
Result: The string representation of the parameter value, without
leading or trailing whitespace.
No concatenation operator following.
(to_integer( ( Vectors(i).OUTPUT ) ) ) returns the integer value for the record element OUTPUT, type signed. (superfluous parentheses aside).
The contents of Vectors(i).OUTPUT is
constant Vectors : VectorArray := (
(OUTPUT_test =>"000011110110"), -- 246 (CORRECT)
(OUTPUT_test =>"000101001000") -- 382 (INCORRECT)
);
The 382 should be 328, its 0x148. Dyslexia is hard to spell.
And in this case for i = 1 (Vectors'RANGE is (0 to 1), is
"000101001000" which to_integer is 328, out of range for an element of a string (element type character).
An integer, value 328 or not is not an element index type for a record (while OUTPUT is).
The subtype for the unnamed string output of 'IMAGE is the length of the string for i, whose value is 1, the length is 1, the range is 1 to 1. 328 is out of range.
Notice the ISIM message said exactly that in the original model:
ERROR: Index 328 out of bound 1 to 1. ERROR: In process TestBenchAutomated.vhd:Test
This still looks like a ghdl error. It does also make nvc's error message suspect however.

VHDL error, even though I generate a bit file

I have made this program in VHDL, alle syntax's are fine, and I have tried to double check all the port maps, but I get some warnings that causes the program not to work, even tough it can generate the bit file.. anybody here who can help please??
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity topMain is
port( clk : in std_logic;
alarm : in std_logic_vector (1 downto 0);
d_open : in std_logic_vector (1 downto 0);
d_closed : in std_logic_vector(1 downto 0);
d_out : out std_logic_vector (1 downto 0));
end topMain;
architecture Behavioral of topMain is
type state_type is (S0,S1,S3);
signal NS, Current_State : state_type;
begin
process (clk, alarm)
begin
if alarm ="11" then
Current_State <= S3; --
elsif rising_edge (clk) then
Current_State <= NS; -- state change
end if;
end process;
--------------------------------
process(Current_State,d_open, d_closed, clk)
begin
case Current_State is
----
when S3 => d_out <= "11";
if (d_open = "10") then
NS <= S3;
elsif (d_closed = "01") then
NS <= S3;
elsif (d_closed = "00") then
NS <= S3;
end if;
----
when S0 => d_out <= "10"; -- open door
if ( d_open = "10" ) then
NS <= S0;
elsif (d_closed= "01") then
NS <= S1;
elsif (d_closed = "10") then
NS <= S0;
else
NS <= S0;
end if;
when S1 => d_out <= "01"; -- open door
if ( d_closed = "01" ) then
NS <= S1;
elsif (d_open <= "10") then
NS <= S0;
elsif (d_open <= "01") then
NS <= S1;
else
NS <= S1;
end if;
end case;
end process;
end Behavioral;
And in case anybody can take a look at it, this is the full project.
Its a simple program containg a finite state machine with 3 changes, simulating a burglar alarm.
When alarm is off, you can open door and close it, but if its on, you cant do anything. at lease thats what i was trying to make, altough i am newbie. Please forgive me for any inconvenience it may cause you.
http://www.abmy.dk/BAlarm.zip
The warnings I am getting right now:
WARNING:Xst:819 - "C:/Xilinx/OP/BAlarm/topMain.vhd" line 36: One or more signals are missing in the process sensitivity list. To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list. Please note that the result of the synthesis may differ from the initial design specification. The missing signals are:
WARNING:Xst:737 - Found 3-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:647 - Input is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
WARNING:PhysDesignRules:372 - Gated clock. Clock net top/NS_not0001 is sourced
by a combinatorial pin. This is not good design practice. Use the CE pin to
control the loading of data into the flip-flop.
WARNING:Route:455 - CLK Net:top/NS_not0001 may have excessive skew because
The NS signal is not assigned in all branches of the combinatorial process
process(Current_State, d_open, d_closed, clk), which will infer latches; see also https://stackoverflow.com/a/20394822/2352082 and https://stackoverflow.com/a/20411227/2352082
The code:
when S3 => d_out <= "11";
if (d_open = "10") then
ns <= S3;
elsif (d_closed = "01") then
ns <= S3;
elsif (d_closed = "00") then
ns <= S3;
end if;
does not have an else, so if neither of the previous conditions
are TRUE, then NS is not assigned, which results in a latch inferred by
synthesis.
You may fix this by adding an else with proper assign NS value assign, like:
...
else
ns <= S0; -- TBD[S0 is only example; use correct value]
end if;
I don't see any signals missing in the process sensitivity list, but clk is
included and not required in the last one, since this process implements combinatorial design.