Reputation: 6647
I need a VHDL entity/architecture that does the exact same thing as this Verilog module below that uses the $setup keyword to check the timing on the inputs. Is there a way to do this natively in VHDL without using mixed VHDL-Verilog simulation?
`timescale 1ns/10ps
module sim_check_setup_posedge(
input wire data_event,
input wire ref_event
);
reg notifier;
specify
specparam tSU = 1; // 1 ns
$setup(data_event, posedge ref_event, tSU, notifier);
endspecify
endmodule
Here's what I have so far for VHDL code:
library ieee;
use ieee.std_logic_1164.all;
entity sim_check_setup_posedge is
port(
data_event :in std_logic;
ref_event :in std_logic
);
end entity;
architecture beh of sim_check_setup_posedge is
begin
-- ?? how to implement $setup here?
end architecuture;
Upvotes: 0
Views: 223
Reputation: 4384
You can easily implement basic timing checks for simulation in VHDL using a combination of predefined attributes (last_event
here) and either checker entities as per your example, or procedures as per a comment. Here's an example setup time checker:
library ieee;
use ieee.std_logic_1164.all;
entity SetupCheckEntity is
generic (
tSU : time
);
port (
data_event :in std_logic;
ref_event :in std_logic
);
end entity;
architecture a of SetupCheckEntity is
begin
SetupCheck : process (ref_event)
begin
if (rising_edge(ref_event)) then
-- Warn if setup time not met or data not valid ('X'/'U')
if (data_event'last_event < tSU or data_event = 'X' or data_event = 'U') then
report "SetupCheckEntity: Setup failure, expected " & time'image(tSU) & ", got " & time'image(data_event'last_event) & "." severity warning;
end if;
end if;
end process;
end a;
You could easily modify this to check relative to either or both ref_event
edge (perhaps dependant on another generic), or extend it to also check hold time. I made the setup time a generic but you could just as easily use a constant. You could also call the procedure below in this entity in place of the process
.
Roughly same code can be put in a procedure as shown in the test bench below that shows both entity and procedure methods giving the same basic result.
library ieee;
use ieee.std_logic_1164.all;
entity test is
end;
architecture a of test is
constant tCK : time := 20 ns;
constant tSU : time := 3 ns;
signal data : std_logic := '0';
signal ref : std_logic := '0';
-- This procedure could be in a package with some other similar procedures
procedure SetupCheckProcedure (signal d,r : in std_logic; constant tSU : in time) is
begin
wait until rising_edge(r);
if (d'last_event < tSU or d = 'X' or d = 'U') then
report "SetupCheckProcedure: Setup failure, expected " & time'image(tSU) & ", got " & time'image(d'last_event) & "." severity warning;
end if;
end procedure;
begin
ref <= not ref after tCK / 2;
-- Data toggling out of sync with ref
data <= not data after (tCK - 1 ns);
SetupChecker : entity work.SetupCheckEntity
generic map (
tSU => tSU
)
port map (
data_event => data,
ref_event => ref
);
SetupCheckProcedure(data, ref, tSU);
end;
Instead of report
you could use some logging package or write to a file.
If you're thinking "wow, all that code to replace one SystemVerilog line", bear in mind that after writing a procedure, you only need SetupCheckProcedure(data, ref, tSU);
, which is pretty well identical to the builtin function in the question.
Upvotes: 1