Commit 22bad477 authored by Jan Pospisil's avatar Jan Pospisil

added UVM testbench suite; typos

parent 9592d604
/hdl/ffpg/wb_gen/*.htm
/hdl/ffpg/wb_gen/*.h
/doc/manual/ffpg_csr.htm
/doc/manual/ffpg_csr.tex
/hdl/ffpg/rtl/ffpg_csr.vhd
/hdl/ffpg/rtl/ffpg_csr_pkg.vhd
/hdl/ffpg/sim/testbench/work/*
/hdl/ffpg/sim/testbench/tr_db.log
/hdl/ffpg/sim/testbench/transcript
/hdl/ffpg/sim/testbench/uvm.log
/hdl/ffpg/sim/testbench/vsim.wlf
/hdl/ffpg/sim/testbench/wlf*
......@@ -4,3 +4,6 @@
[submodule "hdl/ip_cores/wishbone-gen"]
path = hdl/ip_cores/wishbone-gen
url = git://ohwr.org/hdl-core-lib/wishbone-gen.git
[submodule "hdl/ip_cores/uvm_agents"]
path = hdl/ip_cores/uvm_agents
url = https://github.com/AakaFosfor/uvm_agents.git
`ifndef AD5600_INTERFACE_SVH
`define AD5600_INTERFACE_SVH
interface Ad5600Interface;
logic FrameSynchronization_n;
logic SerialClock;
logic SerialData;
modport Dut (output FrameSynchronization_n, SerialClock, SerialData); // FPGA
modport Tb (input FrameSynchronization_n, SerialClock, SerialData); // IC
endinterface
`endif // AD5600_INTERFACE_SVH
\ No newline at end of file
/**
* UVM verification package for AD5620/AD5640/AD5660 DAC
* http://www.analog.com/media/en/technical-documentation/data-sheets/AD5620_5640_5660.pdf
* Revision G, 8/2013
* 2016_06_03, Jan Pospisil, j.pospisil@cern.ch
*/
`ifndef AD5600_PACKAGE_SV
`define AD5600_PACKAGE_SV
`include "uvm_macros.svh"
package Ad5600Package;
import uvm_pkg::*;
let MathMax(a, b) = (a > b) ? a : b;
let MathMin(a, b) = (a < b) ? a : b;
typedef enum {AD5600_TYPE_5620, AD5600_TYPE_5640, AD5600_TYPE_5660} t_ChipType;
typedef enum {AD5600_SUFFIX_1, AD5600_SUFFIX_2, AD5600_SUFFIX_3} t_ChipSuffix;
class Ad5600Chip;
int DataBits[3] = {12, 14, 16};
int RegisterBits[3] = {16, 16, 24};
int DataStartInShiftRegister[3] = {2, 0, 0};
t_ChipType ChipType = AD5600_TYPE_5620;
t_ChipSuffix ChipSuffix = AD5600_SUFFIX_1;
real PowerSupplyVoltage = 0;
// VoltageHigh:
// 0: V_DD = 2.7 V to 3.6 V, maximum SCL frequency = 20 MHz
// 1: V_DD = 3.6 V to 5.5 V, maximum SCL frequency = 30 MHz
bit VoltageHigh = 0;
// ResetValueIsMidscale:
// 0: output value after power-on reset is zero, part-name suffix: -1, -2
// 1: output value after power-on reset is mid-scale, part-name suffix: -3
bit ResetValueIsMidscale = 0;
real VoltageReference = 0;
string Name = "";
function new(t_ChipType ChipType, t_ChipSuffix ChipSuffix, real PowerSupplyVoltage, string Name = "(unknown)");
this.ChipType = ChipType;
this.ChipSuffix = ChipSuffix;
this.PowerSupplyVoltage = PowerSupplyVoltage;
this.Name = Name;
this.VoltageHigh = (PowerSupplyVoltage >= 3.6);
this.ResetValueIsMidscale = (ChipSuffix == AD5600_SUFFIX_3);
this.VoltageReference = ((ChipSuffix == AD5600_SUFFIX_1) ? 1.25 : 2.5);
endfunction
function int getDataBits;
return this.DataBits[this.ChipType];
endfunction
function int getRegisterBits;
return this.RegisterBits[this.ChipType];
endfunction
function int getDataStartInShiftRegister;
return this.DataStartInShiftRegister[this.ChipType];
endfunction
function real getOutputVoltage(int code);
real voltage;
code = code % (2 ** this.getDataBits()); // assert?
voltage = 2 * this.VoltageReference * code / (2 ** this.getDataBits());
voltage = MathMax(voltage, 0);
voltage = MathMin(voltage, this.PowerSupplyVoltage);
return voltage;
endfunction
endclass
class Ad5600Config extends uvm_object;
`uvm_object_utils(Ad5600Config)
virtual Ad5600Interface VirtualInterface;
Ad5600Chip Chip;
function new(string name = "Ad5600Config");
super.new(name);
endfunction: new
endclass
class Ad5600Transaction extends uvm_sequence_item;
rand int VoltageRegister;
Ad5600Chip Chip;
`uvm_object_utils(Ad5600Transaction)
constraint VoltageRegisterConstrain {
VoltageRegister >= 0;
VoltageRegister < 2**Chip.getDataBits();
}
function new (string name = "");
super.new(name);
endfunction
function string convert2string;
return $sformatf("Output voltage on chip \"%s\" changed: REG = 0x%H (%0d), V_out = %f V", this.Chip.Name, this.VoltageRegister, this.VoltageRegister, this.Chip.getOutputVoltage(this.VoltageRegister));
endfunction
endclass
class Ad5600Monitor extends uvm_monitor;
`uvm_component_utils(Ad5600Monitor)
uvm_analysis_port #(Ad5600Transaction) AnalysisPort;
Ad5600Config Configuration;
virtual Ad5600Interface.tb LocalInterface;
Ad5600Chip Chip;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
Configuration = Ad5600Config::type_id::create("config");
AnalysisPort = new("AnalysisPort", this);
assert(uvm_config_db #(Ad5600Config)::get(this, "", "Ad5600Config", Configuration));
LocalInterface = Configuration.VirtualInterface;
Chip = Configuration.Chip;
endfunction
task run_phase(uvm_phase phase);
int dataBits = this.Chip.getDataBits();
int registerBits = this.Chip.getRegisterBits();
bit [31:0] shiftRegister;
Ad5600Transaction tx;
int dataStart = this.Chip.getDataStartInShiftRegister();
forever begin
@(negedge LocalInterface.FrameSynchronization_n);
phase.raise_objection(this);
repeat (registerBits) begin
@(negedge LocalInterface.SerialClock);
// TODO: maximal clock speed assert
shiftRegister = {shiftRegister[0 +: 31], LocalInterface.SerialData};
if (LocalInterface.FrameSynchronization_n)
break;
end
if (~LocalInterface.FrameSynchronization_n) begin
tx = Ad5600Transaction::type_id::create("tx");
tx.VoltageRegister = int'((shiftRegister >> dataStart) & 2**(dataBits)-1);
// TODO: power modes?
tx.Chip = this.Chip;
AnalysisPort.write(tx);
@(posedge LocalInterface.FrameSynchronization_n);
end
phase.drop_objection(this);
end
endtask
endclass
class Ad5600Agent extends uvm_agent;
`uvm_component_utils(Ad5600Agent)
uvm_analysis_port #(Ad5600Transaction) AnalysisPort;
Ad5600Monitor Ad5600Monitor_h;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
AnalysisPort = new("AnalysisPort", this);
Ad5600Monitor_h = Ad5600Monitor::type_id::create("Ad5600Monitor_h", this);
endfunction
function void connect_phase(uvm_phase phase);
Ad5600Monitor_h.AnalysisPort.connect(AnalysisPort);
endfunction
endclass
endpackage
`endif // AD5600_PACKAGE_SV
\ No newline at end of file
`ifndef CONFIG_SVH
`define CONFIG_SVH
// in MHz
`define CLK_FREQ 200
`define WB_ADDRESS_WIDTH 32
`define WB_DATA_WIDTH 32
`define WB_TAG_WIDTH 0
`define WB_REGISTERS 3
`define WB_ADDR_STATUS 0
`define WB_ADDR_TRIGGER_DAC 6
`define WB_ADDR_VCXO_DAC 2
// status bits
`define FFPG_STATUS_DAC_TRIGGER_BUSY 2
`define FFPG_STATUS_DAC_VCXO_BUSY 1
`endif //CONFIG_SVH
`ifndef FFPG_INTERFACE_SVH
`define FFPG_INTERFACE_SVH
`include "Config.svh"
interface FFPGInterface (input bit clk, input bit reset);
Ad5600Interface TriggerDac();
Ad5600Interface VcxoDac();
wishbone_b3_if #(.ADR_W(`WB_ADDRESS_WIDTH), .DAT_W(`WB_DATA_WIDTH), .TAG_W(`WB_TAG_WIDTH)) Wb(clk);
endinterface
`endif // FFPG_INTERFACE_SVH
\ No newline at end of file
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.FfpgCorePkg.all;
entity FfpgCoreWrapper is
generic (
CLK_FREQ: natural -- input clock frequency in MHz
);
port (
-- Wishbone connection
rst_n_i: in std_logic;
clk_sys_i: in std_logic;
wb_adr_i: in std_logic_vector(31 downto 0);
wb_dat_i: in std_logic_vector(31 downto 0);
wb_dat_o: out std_logic_vector(31 downto 0);
wb_cyc_i: in std_logic;
wb_sel_i: in std_logic_vector(3 downto 0);
wb_stb_i: in std_logic;
wb_we_i: in std_logic;
wb_ack_o: out std_logic;
wb_stall_o: out std_logic;
TriggerDacFrameSynchronization_n: out std_logic;
TriggerDacSerialClock: out std_logic;
TriggerDacSerialData: out std_logic;
VcxoDacFrameSynchronization_n: out std_logic;
VcxoDacSerialClock: out std_logic;
VcxoDacSerialData: out std_logic;
ch1_out_en: out std_logic;
ch2_out_en: out std_logic
);
end entity;
architecture syn of FfpgCoreWrapper is
signal TriggerDac_o: t_FfpgAd5600Interface;
signal VcxoDac_o: t_FfpgAd5600Interface;
begin
cFfpgCore: entity work.FfpgCore(syn)
generic map (
CLK_FREQ => CLK_FREQ
)
port map (
rst_n_i => rst_n_i,
clk_sys_i => clk_sys_i,
wb_adr_i => wb_adr_i,
wb_dat_i => wb_dat_i,
wb_dat_o => wb_dat_o,
wb_cyc_i => wb_cyc_i,
wb_sel_i => wb_sel_i,
wb_stb_i => wb_stb_i,
wb_we_i => wb_we_i,
wb_ack_o => wb_ack_o,
wb_stall_o => wb_stall_o,
TriggerDac_o => TriggerDac_o,
VcxoDac_o => VcxoDac_o,
ch1_out_en => ch1_out_en,
ch2_out_en => ch2_out_en
);
TriggerDacFrameSynchronization_n <= TriggerDac_o.FrameSynchronization_n;
TriggerDacSerialClock <= TriggerDac_o.SerialClock;
TriggerDacSerialData <= TriggerDac_o.SerialData;
VcxoDacFrameSynchronization_n <= VcxoDac_o.FrameSynchronization_n;
VcxoDacSerialClock <= VcxoDac_o.SerialClock;
VcxoDacSerialData <= VcxoDac_o.SerialData;
end architecture;
not working on Windows, not working...
sim_tool = "modelsim"
top_module = "Testbench"
action = "simulation"
target = "xilinx"
syn_device = "xc6slx150t"
include_dirs = [
".",
"../../../ip_cores/uvm_agents/src/wishbone_b3",
"c:\Programs\modeltech64_10.4d\verilog_src\uvm-1.2\src"
]
files = [
"Testbench.sv",
"Ad5600Interface.sv",
"Ad5600Package.sv",
"TestbenchPackage.sv",
"../../../ip_cores/uvm_agents/src/wishbone_b3/wishbone_b3_if.sv",
"../../../ip_cores/uvm_agents/src/wishbone_b3/wishbone_b3_package.sv"
]
modules = {
"local": [
"../../rtl"
]
}
fetchto = "../../../ip_cores"
\ No newline at end of file
`include "Config.svh"
import uvm_pkg::*;
import Ad5600Package::*;
import TestbenchPackage::*;
module Testbench;
timeunit 1ns;
parameter CLK_PERIOD = 1000/`CLK_FREQ;
bit clk, reset;
bit wb_ack;
FFPGInterface LocalInterface(clk, reset);
FfpgCoreWrapper #(
.CLK_FREQ(200)
) dut (
.rst_n_i(~reset),
.clk_sys_i(clk),
.wb_adr_i(LocalInterface.Wb.adr),
.wb_dat_i(LocalInterface.Wb.dat_o),
.wb_dat_o(LocalInterface.Wb.dat_i),
.wb_cyc_i(LocalInterface.Wb.cyc),
.wb_sel_i(LocalInterface.Wb.sel),
.wb_stb_i(LocalInterface.Wb.stb),
.wb_we_i(LocalInterface.Wb.we),
.wb_ack_o(wb_ack),
.wb_stall_o(), // doesn't exist in B3 version of WB
.TriggerDacFrameSynchronization_n(LocalInterface.TriggerDac.FrameSynchronization_n),
.TriggerDacSerialClock(LocalInterface.TriggerDac.SerialClock),
.TriggerDacSerialData(LocalInterface.TriggerDac.SerialData),
.VcxoDacFrameSynchronization_n(LocalInterface.VcxoDac.FrameSynchronization_n),
.VcxoDacSerialClock(LocalInterface.VcxoDac.SerialClock),
.VcxoDacSerialData(LocalInterface.VcxoDac.SerialData),
.ch1_out_en(), // not tested so far
.ch2_out_en() // not tested so far
);
initial begin: unusedWbSignals
LocalInterface.Wb.err = 0;
LocalInterface.Wb.rty = 0;
end
assign LocalInterface.Wb.ack = wb_ack;
initial begin: clockGenerator
clk = 0;
forever #(CLK_PERIOD/2) clk = ~clk;
end
initial begin: resetGenerator
reset = 1;
repeat(3) @(negedge clk);
reset = 0;
end
assign LocalInterface.Wb.rst_i = reset;
initial begin: mainTest
uvm_config_db #(virtual FFPGInterface)::set(null, "uvm_test_top.*", "dut_vi", LocalInterface);
uvm_top.finish_on_completion = 0; // not to finish when GUI is used
run_test("TestTriggerAdc");
$stop();
end
initial begin: timeout
#100us $error("Simulation timeout!");
$stop();
end
endmodule
\ No newline at end of file
This diff is collapsed.
vcom -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/genrams/genram_pkg.vhd
vcom -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/genrams/memory_loader_pkg.vhd
vcom -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/genrams/xilinx/generic_dpram.vhd
vcom -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/genrams/xilinx/generic_dpram_dualclock.vhd
vcom -reportprogress 300 -work work ../../../ip_cores/wishbone-gen/lib/wbgen2_pkg.vhd
vcom -reportprogress 300 -work work ../../../ip_cores/wishbone-gen/lib/wbgen2_dpssram.vhd
vcom -reportprogress 300 -work work ../../../ip_cores/wishbone-gen/lib/wbgen2_eic.vhd
vcom -reportprogress 300 -work work ../../../ip_cores/wishbone-gen/lib/wbgen2_fifo_async.vhd
vcom -reportprogress 300 -work work ../../../ip_cores/wishbone-gen/lib/wbgen2_fifo_sync.vhd
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/common/gc_serial_dac.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/ffpg_csr_pkg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/ffpg_csr.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/FfpgCorePkg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/FfpgCore.vhd
vlog -reportprogress 300 -work work Ad5600Interface.sv
vlog -reportprogress 300 -work work Ad5600Package.sv
vlog -reportprogress 300 -work work ../../../ip_cores/uvm_agents/src/wishbone_b3/wishbone_b3_if.sv
vlog -reportprogress 300 -work work ../../../ip_cores/uvm_agents/src/wishbone_b3/wishbone_b3_package.sv
vlog -reportprogress 300 -work work TestbenchPackage.sv
vlog -reportprogress 300 -work work FFPGInterface.sv
vcom -2008 -reportprogress 300 -work work FfpgCoreWrapper.vhd
vlog -reportprogress 300 -work work Testbench.sv
do make
do res
\ No newline at end of file
restart -force -sv_seed random
run -all
\ No newline at end of file
vsim -voptargs=+acc work.Testbench
add wave -r -group Interface sim:/Testbench/LocalInterface/*
add wave -group DUT sim:/Testbench/LocalInterface/clk
add wave -group DUT sim:/Testbench/dut/cFfpgCore/*
add wave -group WbSlave sim:/Testbench/dut/cFfpgCore/cWbSlave/*
add wave -group "Trigger DAC module" sim:/Testbench/dut/cFfpgCore/cTriggerDac/*
add wave -group "VCXO DAC module" sim:/Testbench/dut/cFfpgCore/cVcxoDac/*
configure wave -signalnamewidth 1
sv_reseed random
run -all
\ No newline at end of file
WBGEN2=wbgen2
RTL=../rtl/
TEX=../../../doc/manual/
DOC=../../../doc/manual/
%:
$(WBGEN2) -l vhdl -H record -V $(RTL)$@.vhd -p $(RTL)$@_pkg.vhd -f html -D $@.htm -C $@.h $@.wb
$(WBGEN2) -f texinfo -D $(TEX)$@.tex $@.wb
\ No newline at end of file
$(WBGEN2) -l vhdl -H record -V $(RTL)$@.vhd -p $(RTL)$@_pkg.vhd -f html -D $(DOC)$@.htm -C $@.h $@.wb
$(WBGEN2) -f texinfo -D $(DOC)$@.tex $@.wb
\ No newline at end of file
Subproject commit c02784d959888cc1b8e9db3b7780f95a404071ff
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment