Commit bcd4ba2d authored by Jan Pospisil's avatar Jan Pospisil

added WB-SPI core for AD9512 (HW control disconnected)

parent 08a34e9d
......@@ -96,22 +96,43 @@ architecture syn of FfpgCore is
constant c_NumWbMasters: integer := 1;
-- Number of master port(s) on the wishbone crossbar
constant c_NumWbSlaves: integer := 2;
constant c_NumWbSlaves: integer := 3;
-- Wishbone master(s)
constant c_MasterId: integer := 0;
-- Wishbone slave(s)
constant c_SlaveTemperatureId: integer := 0;
constant c_SlaveFfpgId: integer := 1;
constant c_SlaveAd9512Id: integer := 1;
constant c_SlaveFfpgId: integer := 2;
-- sdb header address
constant c_SdbAddress: t_wishbone_address := x"0000_0000";
constant c_Ad9512Sdb : t_sdb_device := (
abi_class => x"0000", -- undocumented device
abi_ver_major => x"01",
abi_ver_minor => x"01",
wbd_endian => c_sdb_endian_big,
wbd_width => x"7", -- 8/16/32-bit port granularity
sdb_component => (
addr_first => x"0000000000000000",
addr_last => x"00000000000000ff",
product => (
vendor_id => x"000000000000CE42", -- CERN
device_id => x"01010101",
version => x"00000001",
date => x"20170330",
name => "AD9512 SPI Ctrl. "
)
)
);
-- Wishbone crossbar layout
constant c_InterconnectLayout: t_sdb_record_array(c_NumWbSlaves-1 downto 0) := (
0 => f_sdb_embed_device(c_xwb_onewire_master_sdb, x"0000_1000"),
1 => f_sdb_embed_device(c_FfpgSdbDevice, x"0001_0000")
1 => f_sdb_embed_device(c_Ad9512Sdb, x"0000_2000"),
2 => f_sdb_embed_device(c_FfpgSdbDevice, x"0001_0000")
);
signal Reset_r, Reset_nr: std_logic;
......@@ -127,6 +148,9 @@ architecture syn of FfpgCore is
-- Onewire
signal OwrEn, Owr: std_logic;
-- SPI
signal ChipSelect_b32: std_logic_vector(31 downto 0);
begin
cResetSyncerSys: entity work.ResetSyncer(syn)
......@@ -196,10 +220,10 @@ begin
Trigger_i => Trigger_i,
Clk2Sel_o => Clk2Sel_o,
Led_ob => Led_ob,
SpiAd9512Cs_on => SpiAd9512Cs_on,
SpiAd9512Sclk_o => SpiAd9512Sclk_o,
SpiAd9512Mosi_o => SpiAd9512Mosi_o,
SpiAd9512Miso_i => SpiAd9512Miso_i,
SpiAd9512Cs_on => open,
SpiAd9512Sclk_o => open,
SpiAd9512Mosi_o => open,
SpiAd9512Miso_i => '1',
Ad9512Func_o => Ad9512Func_o,
ClkOut_ok => ClkOut_ok
);
......@@ -238,4 +262,33 @@ begin
'Z';
Owr <= Onewire_io;
----------------------------------
-- AD9512 SPI slave
----------------------------------
cSpiMasterWb: entity work.SpiMasterWb
port map (
Clk_ik => Clk_ik,
Rst_irq => Reset_r,
Cyc_i => CnxMasterOut(c_SlaveAd9512Id).cyc,
Stb_i => CnxMasterOut(c_SlaveAd9512Id).stb,
We_i => CnxMasterOut(c_SlaveAd9512Id).we,
Adr_ib3 => CnxMasterOut(c_SlaveAd9512Id).adr(4 downto 2),
Dat_ib32 => CnxMasterOut(c_SlaveAd9512Id).dat,
Dat_oab32 => CnxMasterIn(c_SlaveAd9512Id).dat,
Ack_oa => CnxMasterIn(c_SlaveAd9512Id).ack,
WaitingNewData_o => open,
ModuleIdle_o => open,
SClk_o => SpiAd9512Sclk_o,
MoSi_o => SpiAd9512Mosi_o,
MiSo_ib32(0) => SpiAd9512Miso_i,
MiSo_ib32(31 downto 1) => "0000000000000000000000000000000",
SS_onb32 => ChipSelect_b32
);
CnxMasterIn(c_SlaveAd9512Id).err <= '0';
CnxMasterIn(c_SlaveAd9512Id).rty <= '0';
CnxMasterIn(c_SlaveAd9512Id).stall <= '0';
CnxMasterIn(c_SlaveAd9512Id).int <= '0';
SpiAd9512Cs_on <= ChipSelect_b32(0);
end architecture;
/*
* This is a SPI master for up to 32 independent slaves
* The module support the following configurations:
* - Any CPol CPha combination
* - The length of the reg is programmable up to 256 allowing
* the concatenation of several slaves, if the access is longer
* than 32 bits between 2 registers the communication is paused
* - MSB or LSB first
* - The speed of the clock is settable
* - It is possible to put a wait state between the falling edge
* of SS (Slave Select) and the 1st edge of SClk as requested by some
* ADC
*
* Configuration:
*
* CONFIG1
* +--------+--------+----------+-------+-----------------+-------+----------------------+
* | a_CPol | a_CPha | a_Lsb1St | | a_SpiChannel_b5 | | a_RegisterLenght_b12 |
* +--------+--------+----------+-------+-----------------+-------+----------------------+
* 31 30 29 28:21 20:16 15:12 11:0
*
* a_CPol - default state of SClk_o
* a_CPha - SClk_o phase:
* 0 - data are sampled on the first SClk_o edge
* 1 - data are sampled on the second SClk_o edge
* a_Lsb1St - whether to send/receive LSB first
* a_SpiChannel_b5 - SS_onb32 and MiSo_ib32 channel concerned
* a_RegisterLenght_b12 - bit length of the data being send/receive
*
* CONFIG2
* +---------------------+----------------+
* | a_ClkSemiPeriod_b16 | a_WaitTime_b16 |
* +---------------------+----------------+
* 31:16 15:0
*
* a_ClkSemiPeriod_b16 - # of Clk_ik cycles for half of the SClk_o period
* Example: Clk_ik frequency = 125 MHz, a_ClkSemiPeriod_b16 = 2, SClk_o frequency = 31.25 MHz
* a_WaitTime_b16 - minimum # of Clk_ik cycles of idle state before start of transaction
*
*/
`timescale 1ns/100ps
module SpiMasterWb (
input Clk_ik,
input Rst_irq,
input Cyc_i,
input Stb_i,
input We_i,
input [2:0] Adr_ib3,
input [31:0] Dat_ib32,
output reg [31:0] Dat_oab32,
output reg Ack_oa,
output reg WaitingNewData_o,
output reg ModuleIdle_o,
output reg SClk_o,
output MoSi_o,
input [31:0] MiSo_ib32,
output reg [31:0] SS_onb32);
localparam c_AddrStatus = 3'd0,
c_AddrConfig1 = 3'd1,
c_AddrConfig2 = 3'd2,
c_AddrShiftOut = 3'd3,
c_AddrShiftIn = 3'd4;
reg [31:0] Config2_qb32,
ShiftOut_qb32,
ShiftIn_qb32,
Config1_qb32;
wire a_CPol = Config1_qb32[31];
wire a_CPha = Config1_qb32[30];
wire a_Lsb1St = Config1_qb32[29];
wire [4:0] a_SpiChannel_b5 = Config1_qb32[20:16];
wire [11:0] a_RegisterLenght_b12 = Config1_qb32[11:0];
wire [15:0] a_ClkSemiPeriod_b16 = Config2_qb32[31:16];
wire [15:0] a_WaitTime_b16 = Config2_qb32[15:0];
reg [2:0] State_a,
State_q;
localparam s_Idle = 3'd0,
s_WaitBefore1StEdge = 3'd1,
s_EdgeTypeOne = 3'd2,
s_EdgeTypeTwo = 3'd3,
s_TxPause = 3'd4,
s_EndOfTx = 3'd5;
reg [15:0] TimeCounter_cb16;
reg [11:0] TxCounter_cb12;
reg WriteAck_q, StartTx_q;
always @(posedge Clk_ik)
if (Rst_irq) State_q <= s_Idle;
else State_q <= State_a;
always @* begin
State_a = State_q;
case (State_q)
s_Idle: if (StartTx_q) State_a = s_WaitBefore1StEdge;
s_WaitBefore1StEdge: if (TimeCounter_cb16==a_WaitTime_b16) State_a = s_EdgeTypeOne;
s_EdgeTypeOne: if (TimeCounter_cb16==a_ClkSemiPeriod_b16) State_a = s_EdgeTypeTwo;
s_EdgeTypeTwo: if (TimeCounter_cb16==a_ClkSemiPeriod_b16)
if (TxCounter_cb12==a_RegisterLenght_b12) State_a = s_EndOfTx;
else if (|TxCounter_cb12[4:0]) State_a = s_EdgeTypeOne;
else State_a = s_TxPause;
s_TxPause: if (StartTx_q) State_a = s_EdgeTypeOne;
s_EndOfTx: if (TimeCounter_cb16==a_ClkSemiPeriod_b16) State_a = s_Idle;
default: State_a = s_Idle;
endcase
end
assign MoSi_o = a_Lsb1St ? ShiftOut_qb32[0] : ShiftOut_qb32[31];
always @(posedge Clk_ik) begin
WriteAck_q <= WriteAck_q && Stb_i; // Default clear condition valid for all the states
ModuleIdle_o <= 'h0;
WaitingNewData_o <= 'h0;
if (Rst_irq) begin
StartTx_q <= 'b0;
WriteAck_q <= 'b0;
SClk_o <= 'b0;
SS_onb32 <= 32'hFFFF_FFFF;
TimeCounter_cb16 <= 'h0;
TxCounter_cb12 <= 'h0;
Config1_qb32 <= 'h0;
Config2_qb32 <= 'h0;
ShiftOut_qb32 <= 'h0;
ShiftIn_qb32 <= 'h0;
ModuleIdle_o <= 'h0;
WaitingNewData_o <= 'h0;
end else case (State_q)
s_Idle: begin
SClk_o <= a_CPol;
SS_onb32 <= 32'hFFFF_FFFF;
TimeCounter_cb16 <= 'h0;
TxCounter_cb12 <= 'h0;
ModuleIdle_o <= State_a==s_Idle;
if (Cyc_i && We_i && Stb_i && Adr_ib3==c_AddrShiftOut) begin
ShiftOut_qb32 <= Dat_ib32;
ShiftIn_qb32 <= 'h0;
WriteAck_q <= 1'b1;
StartTx_q <= 1'b1;
end else if (Cyc_i && We_i && Stb_i && Adr_ib3==c_AddrConfig1) begin
Config1_qb32 <= Dat_ib32;
WriteAck_q <= 1'b1;
end else if (Cyc_i && We_i && Stb_i && Adr_ib3==c_AddrConfig2) begin
Config2_qb32 <= Dat_ib32;
WriteAck_q <= 1'b1;
end
end
s_WaitBefore1StEdge: begin
TimeCounter_cb16 <= TimeCounter_cb16 + 1'b1;
SS_onb32[a_SpiChannel_b5] <= 1'b0;
if (State_a==s_EdgeTypeOne) TimeCounter_cb16 <= 'h0;
end
s_EdgeTypeOne: begin
TimeCounter_cb16 <= TimeCounter_cb16 + 1'b1;
if (State_a==s_EdgeTypeTwo) begin
TimeCounter_cb16 <= 'h0;
SClk_o <= ~SClk_o;
TxCounter_cb12 <= TxCounter_cb12 + 1'b1;
StartTx_q <= 'h0;
if (a_CPha && ~StartTx_q) ShiftOut_qb32 <= a_Lsb1St ? {ShiftOut_qb32[0], ShiftOut_qb32[31:1]} : {ShiftOut_qb32[30:0], ShiftOut_qb32[31]};
else if (~a_CPha) ShiftIn_qb32 <= a_Lsb1St ? {MiSo_ib32[a_SpiChannel_b5], ShiftIn_qb32[31:1]} : {ShiftIn_qb32[30:0], MiSo_ib32[a_SpiChannel_b5]};
end
end
s_EdgeTypeTwo: begin
TimeCounter_cb16 <= TimeCounter_cb16 + 1'b1;
if (State_a!=s_EdgeTypeTwo) begin
SClk_o <= ~SClk_o;
TimeCounter_cb16 <= 'h0;
if (~a_CPha)ShiftOut_qb32 <= a_Lsb1St ? {ShiftOut_qb32[0], ShiftOut_qb32[31:1]} : {ShiftOut_qb32[30:0], ShiftOut_qb32[31]};
else ShiftIn_qb32 <= a_Lsb1St ? {MiSo_ib32[a_SpiChannel_b5], ShiftIn_qb32[31:1]} : {ShiftIn_qb32[30:0], MiSo_ib32[a_SpiChannel_b5]};
end
end
s_TxPause: begin
WaitingNewData_o <= State_a==s_TxPause;
if (Cyc_i && We_i && Stb_i && Adr_ib3==c_AddrShiftOut) begin
ShiftOut_qb32 <= Dat_ib32;
ShiftIn_qb32 <= 'h0;
WriteAck_q <= 1'b1;
StartTx_q <= 1'b1;
end
end
s_EndOfTx: begin
TimeCounter_cb16 <= TimeCounter_cb16 + 1'b1;
if (State_a==s_Idle) SS_onb32 <= 32'hFFFF_FFFF;
end
default: begin
StartTx_q <= 'b0;
WriteAck_q <= 'b0;
SClk_o <= 'b0;
SS_onb32 <= 32'hFFFF_FFFF;
TimeCounter_cb16 <= 'h0;
TxCounter_cb12 <= 'h0;
Config1_qb32 <= 'h0;
Config2_qb32 <= 'h0;
ShiftOut_qb32 <= 'h0;
ShiftIn_qb32 <= 'h0;
ModuleIdle_o <= 'h0;
WaitingNewData_o <= 'h0;
end
endcase
end
always @* begin
Ack_oa <= (Stb_i&&Cyc_i&&~We_i) || WriteAck_q;
case (Adr_ib3)
c_AddrStatus: Dat_oab32 <= {12'h0, 1'b0, State_q, 4'b0, TxCounter_cb12};
c_AddrConfig1: Dat_oab32 <= Config1_qb32;
c_AddrConfig2: Dat_oab32 <= Config2_qb32;
c_AddrShiftOut: Dat_oab32 <= ShiftOut_qb32;
c_AddrShiftIn: Dat_oab32 <= ShiftIn_qb32;
default: Dat_oab32 <= 32'hDEAD_BEEF;
endcase
end
endmodule
\ No newline at end of file
......@@ -118,7 +118,8 @@ module Testbench;
// run_test("TestDelayConfiguration");
// run_test("TestPulseGenerationBlind");
// run_test("TestPulseGenerationSequential");
run_test("TestPulseGeneration");
// run_test("TestPulseGeneration");
run_test("TestAd9512Communication");
$stop();
end
......
......@@ -314,6 +314,7 @@ package TestbenchPackage;
`uvm_fatal("CONF", "No DUT virtual interface set")
WbConfig.is_active = UVM_ACTIVE;
WbConfig.timeout = 100;
WbAgent = td_wb_agent::type_id::create("WbAgent", this);
WbAgent.cfg = WbConfig;
WbAgent.sigs = LocalInterface.Wb;
......@@ -567,7 +568,7 @@ package TestbenchPackage;
start_item(tx);
assert(tx.randomize());
tx.direction_e = WB_B3_DIR_WRITE;
tx.address = `GET_WB_FFPG_ADDR(`ADDR_FFPG_TRIGGER_LATENCY);
tx.address = (Channel == 1) ? `GET_WB_FFPG_ADDR(`ADDR_FFPG_CH1_TRIGGER_LATENCY) : `GET_WB_FFPG_ADDR(`ADDR_FFPG_CH2_TRIGGER_LATENCY);
tx.data = this.TriggerLatency;
finish_item(tx);
assert(tx.response_e == WB_B3_RESPONSE_ACK_OK);
......@@ -744,6 +745,43 @@ package TestbenchPackage;
endclass
class SeqAd9512 extends ReportingSequence #(td_wb_tx);
`uvm_object_utils(SeqAd9512)
function new (string name = "");
super.new(name);
endfunction
task writeWbRegister(logic [31:0] address, logic [31:0] data);
td_wb_tx tx = td_wb_tx::type_id::create("tx");
start_item(tx);
assert(tx.randomize());
tx.direction_e = WB_B3_DIR_WRITE;
tx.address = address;
tx.data = data;
finish_item(tx);
endtask
task body;
logic [31:0] spiBaseAddress = 32'h00002000;
writeWbRegister(spiBaseAddress + 1, 32'hC0000018);
writeWbRegister(spiBaseAddress + 2, 32'h50005);
writeWbRegister(spiBaseAddress + 3, 32'h204a5500);
#10000;
// // read CONFIG1
// tx = td_wb_tx::type_id::create("tx");
// start_item(tx);
// assert(tx.randomize());
// tx.direction_e = WB_B3_DIR_READ;
// tx.address = 32'h00002001;
// finish_item(tx);
endtask
endclass
class TestBase extends uvm_test;
`uvm_component_utils(TestBase)
......@@ -971,4 +1009,29 @@ package TestbenchPackage;
endclass
class TestAd9512Communication extends TestBase;
`uvm_component_utils(TestAd9512Communication)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase(uvm_phase phase);
SeqAd9512 seq;
phase.raise_objection(this);
#100;
seq = SeqAd9512::type_id::create("seq");
assert(seq.randomize());
seq.start(Env_h.WbAgent.seqr);
phase.drop_objection(this);
endtask
endclass
endpackage
\ No newline at end of file
......@@ -30,6 +30,7 @@ vcom -2008 -reportprogress 300 -work work ../../rtl/Reg.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/RegSyncer.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/SlowToggle.vhd
vcom -2008 -reportprogress 300 -work work ../../rtl/FrequencySense.vhd
vlog -reportprogress 300 -work work ../../rtl/SpiMasterWb.v
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/wishbone/wishbone_pkg.vhd
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd
......
......@@ -201,9 +201,9 @@ module Testbench;
endtask
task automatic TestReal;
`include "z:/wb_trace.svh"
#1ms;
WbRead(`WB_FFPG_CSR_REG(`ADDR_FFPG_DEBUG), dataOut, "Debug");
`include "z:/FFPG/wb_trace.svh"
// #1ms;
// WbRead(`WB_FFPG_CSR_REG(`ADDR_FFPG_DEBUG), dataOut, "Debug");
endtask
task automatic TestAd9512Sync;
......@@ -232,11 +232,13 @@ module Testbench;
WaitUntilRead;
#5us
// TestSdb;
// TestFfpgCsr;
// TestReal;
TestAd9512Sync;
TestAd9512Sync;
TestReal;
// TestAd9512Sync;
// TestAd9512Sync;
// uint64_t blt_addr[];
// uint64_t blt_data[];
......
......@@ -32,6 +32,7 @@ vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/Reg.vhd
vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/RegSyncer.vhd
vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/SlowToggle.vhd
vcom -2008 -reportprogress 300 -work work ../../../ffpg/rtl/FrequencySense.vhd
vlog -reportprogress 300 -work work ../../../ffpg/rtl/SpiMasterWb.v
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/wishbone/wishbone_pkg.vhd
vcom -2008 -reportprogress 300 -work work ../../../ip_cores/general-cores/modules/wishbone/wb_slave_adapter/wb_slave_adapter.vhd
......
......@@ -4,29 +4,31 @@ vsim -voptargs=+acc work.Testbench
add wave -group DUT sim:/Testbench/cDut/cSvecTopFfpg/*
# add wave -group {Xbar SVEC} sim:/Testbench/cDut/cSvecTopFfpg/cWbSdbCrossbar/*
# add wave -group {Xbar FFPG} sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cWbSdbCrossbar/*
# add wave -group {Xbar FFPGCore} sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cWbSdbCrossbar/*
add wave -group FFPG sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/*
add wave -group FFPGCore sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/*
# add wave -group FFPG -group WbSlave sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cWbSlaveWrapper/*
# add wave -group FFPG -group DacsController sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDacsController/*
# add wave -group FFPG -group DelayController -r sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayController/*
add wave -group FFPGSlave sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/*
add wave -group FFPG -group DelayedPulseGeneratorsCdc sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/*
# add wave -group FFPGSlave -group WbSlave sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cWbSlaveWrapper/*
# add wave -group FFPGSlave -group DacsController sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDacsController/*
# add wave -group FFPGSlave -group DelayController -r sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayController/*
add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/*
add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group Fsm sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cFsm/*
add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group BitCounter sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cBitCounter/*
add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group StreamCounter sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cStreamCounter/*
add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group ShiftRegisterSet sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cShiftRegisterSet/*
add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group ShiftRegisterReset sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cShiftRegisterReset/*
add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/*
# add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/*
# add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group Fsm sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cFsm/*
# add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group BitCounter sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cBitCounter/*
# add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group StreamCounter sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cStreamCounter/*
# add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group ShiftRegisterSet sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cShiftRegisterSet/*
# add wave -group FFPG -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group ShiftRegisterReset sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cShiftRegisterReset/*
add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/*
add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group Fsm sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cFsm/*
add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group BitCounter sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cBitCounter/*
add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group StreamCounter sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cStreamCounter/*
add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group ShiftRegisterSet sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cShiftRegisterSet/*
add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh1 -group ShiftRegisterReset sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh1/cShiftRegisterReset/*
# add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/*
# add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group Fsm sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cFsm/*
# add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group BitCounter sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cBitCounter/*
# add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group StreamCounter sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cStreamCounter/*
# add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group ShiftRegisterSet sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cShiftRegisterSet/*
# add wave -group FFPGSlave -group DelayedPulseGeneratorsCdc -group DelayedPulseGeneratorCh2 -group ShiftRegisterReset sim:/Testbench/cDut/cSvecTopFfpg/cFmc0FfpgCore/cFfpgSlave/cDelayedPulseGeneratorsCdc/cDelayedPulseGeneratorCh2/cShiftRegisterReset/*
configure wave -namecolwidth 271
configure wave -valuecolwidth 100
......
......@@ -380,15 +380,15 @@
<files>
<file xil_pn:name="../rtl/SvecTopFfpg.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="Implementation" xil_pn:seqID="71"/>
<association xil_pn:name="Implementation" xil_pn:seqID="72"/>
</file>
<file xil_pn:name="../../ffpg/rtl/FfpgCore.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="2"/>
<association xil_pn:name="Implementation" xil_pn:seqID="70"/>
<association xil_pn:name="Implementation" xil_pn:seqID="71"/>
</file>
<file xil_pn:name="../../ffpg/rtl/FfpgSlave.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="3"/>
<association xil_pn:name="Implementation" xil_pn:seqID="64"/>
<association xil_pn:name="Implementation" xil_pn:seqID="65"/>
</file>
<file xil_pn:name="../../ffpg/rtl/DacsController.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="4"/>
......@@ -540,7 +540,7 @@
</file>
<file xil_pn:name="../../ip_cores/vme64x-core/hdl/vme64x-core/rtl/xvme64x_core.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="60"/>
<association xil_pn:name="Implementation" xil_pn:seqID="67"/>
<association xil_pn:name="Implementation" xil_pn:seqID="68"/>
</file>
<file xil_pn:name="../../ip_cores/vme64x-core/hdl/vme64x-core/rtl/VME64xCore_Top.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="61"/>
......@@ -604,7 +604,7 @@
</file>
<file xil_pn:name="../../ip_cores/general-cores/modules/wishbone/wb_i2c_master/xwb_i2c_master.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="81"/>
<association xil_pn:name="Implementation" xil_pn:seqID="68"/>
<association xil_pn:name="Implementation" xil_pn:seqID="69"/>
</file>
<file xil_pn:name="../../ip_cores/general-cores/modules/wishbone/wb_i2c_master/wb_i2c_master.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="82"/>
......@@ -624,7 +624,7 @@
</file>
<file xil_pn:name="../rtl/carrier_csr.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="86"/>
<association xil_pn:name="Implementation" xil_pn:seqID="66"/>
<association xil_pn:name="Implementation" xil_pn:seqID="67"/>
</file>
<file xil_pn:name="../../ffpg/rtl/SlowToggle.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="87"/>
......@@ -632,14 +632,14 @@
</file>
<file xil_pn:name="../../ip_cores/general-cores/modules/common/gc_bicolor_led_ctrl.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="88"/>
<association xil_pn:name="Implementation" xil_pn:seqID="69"/>
<association xil_pn:name="Implementation" xil_pn:seqID="70"/>
</file>
<file xil_pn:name="SvecFfpg.ucf" xil_pn:type="FILE_UCF">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
<file xil_pn:name="../rtl/HeartBeat.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="126"/>
<association xil_pn:name="Implementation" xil_pn:seqID="65"/>
<association xil_pn:name="Implementation" xil_pn:seqID="66"/>
</file>
<file xil_pn:name="../../ffpg/rtl/DelayedPulseGenerator/DelayedPulseGeneratorsCdc.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="152"/>
......@@ -665,6 +665,10 @@
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="126"/>
<association xil_pn:name="Implementation" xil_pn:seqID="43"/>
</file>
<file xil_pn:name="../../ffpg/rtl/SpiMasterWb.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="125"/>
<association xil_pn:name="Implementation" xil_pn:seqID="64"/>
</file>
</files>
<bindings>
......
from Spi import *
class AD9512(Spi):
Ad9512Config = {
"Channel": 0,
"CPol": 1,
"CPha": 1,
"LSB1st": 0,
"Length": 24,
"HalfPeriod": 5, # 10 MHz
"WaitTime": 5
}
def __init__(self, wbOverlay, SpiBaseAddress, SpiOffset = 0):
super(AD9512, self).__init__(wbOverlay, self.Ad9512Config, SpiBaseAddress, SpiOffset)
def Write(self, Address, Data, SelfCommit = False):
RnW = 0
Length = 1 # only 1 byte transaction supported
Address &= 2**13-1
Data &= 2**8-1
DataLow = (RnW<<23) + (Length<<21) + (Address<<8) + Data
self._debug("AD9512 SPI Write: 0x%06x" % DataLow)
self.SpiAccess(DataLow)
if SelfCommit:
self.Commit()
def Read(self, Address):
RnW = 1
Length = 1 # only 1 byte transaction supported
Address &= 2**13-1
DataLow = (RnW<<23) + (Length<<21) + (Address<<8)
self._debug("AD9512 SPI Read: 0x%06x" % DataLow)
Data = self.SpiAccess(DataLow)
self._debug("AD9512 SPI Read result: 0x%06x" % Data)
Data &= 2**8-1
return Data
def Commit(self):
self.Write(0x5a, 1)
\ No newline at end of file
......@@ -90,3 +90,9 @@ def PrintBits(value, bitFrom, bitTo, label, descriptions):
description = "<unknown>"
print(color+" "+str(value)+": "+description+ConColors.NONE)
def ErrorMsg(Text):
print(ConColors.RED+ConColors.BOLD+"!!! Error: "+ConColors.NONE+ConColors.RED+Text+ConColors.NONE)
def OkMsg(Text):
print(ConColors.GREEN+ConColors.BOLD+"OK: "+ConColors.NONE+Text)
......@@ -50,6 +50,8 @@
## 2016-09-21 1.5 Jan Pospisil added calibration example code
##-----------------------------------------------------------------------------
import time
from CommonFunctions import *
from Ffpg import *
# triggerPhase = 53.76 # same for both channels in the test setup
......@@ -62,11 +64,57 @@ calibrationData = [ # -1 = uncalibrated
fmcSlot = 1 # 0 | 1
channel = 2 # 1 | 2
ad9512Config = (
(0x34, 0x01),
(0x35, 0x00),
(0x36, 0x00),
(0x3f, 0x03),
(0x45, 0x05),
(0x4a, 0x00),
(0x4c, 0x00),
(0x4e, 0x00),
(0x50, 0x00),
(0x52, 0x00),
(0x4b, 0x00),
(0x4d, 0x00),
(0x4f, 0x00),
(0x51, 0x00),
(0x53, 0x00),
(0x58, 0x20)
)
def Ad9512Config(pg, Config):
for Register in Config:
Address = Register[0]
Data = Register[1]
pg.ad9512.Write(Address, Data)
pg.ad9512.Commit()
def Ad9512Check(pg, Config):
print "Checking AD9512 configuration..."
errors = 0
for Register in Config:
Address = Register[0]
Data = Register[1]
DataRead = pg.ad9512.Read(Address)
if Data <> DataRead:
ErrorMsg("Data at address 0x%02x are different! Data read = 0x%02x, should be 0x%02x" % (Address, DataRead, Data))
errors += 1
if errors == 0:
OkMsg("no error found")
else:
ErrorMsg("found %d errors!" % errors)
def Init(pg):
global calibrationData
global ad9512Config
pg.Reset()
pg.SelectClock("external", 400.789)
pg.SetRatio(2)
Ad9512Config(pg, ad9512Config)
pg.SetOverflow(17820)
pg.Ad9512Sync()
pg.SetTriggerThreshold(0.5)
......@@ -117,22 +165,48 @@ pg = Ffpg(fmcSlot)
Init(pg)
# create single pulse
# TestSinglePulse(pg, channel)
TestSinglePulse(pg, channel)
# create bunched pulses
TestBunchPulses(pg, channel)
# TestBunchPulses(pg, channel)
# stop and disable channel
# StopAndDisable(pg, channel)
# print some info
pg.PrintVersion()
print("Actual temperature: "+str(pg.temp.ReadTemperature()) + " °C")
# print("Actual temperature: "+str(pg.temp.ReadTemperature()) + " °C")
PrintFrequency(pg)
pg.PrintControl()
pg.PrintStatus()
pg.PrintDebug()
# pg.ad9512.debug = True
# pg.wb.SetDebug(True)
# pg.wb.SetDebugSv("wb_trace.svh")
# pg.wb.Read("version")
# # reg = "ch2_res_mem"
# reg = "SpiBase"
# for i in range(10):
# pg.wb.Write(reg, i, Offset=i)
# for i in range(10):
# pg.wb.Read(reg, Offset=i)
# pg.wb.SetDebugSv("")
# pg.wb.SetDebugSv("wb_trace.svh")
# # pg.ad9512._WriteConfig1(0x55)
# # pg.wb.Read("SpiBase", Offset = 1)
# pg.ad9512.Write(0x4A, 0x55)
# pg.ad9512.Write(0x5A, 0x1)
# print(hex(pg.ad9512.Read(0x4A)))
# pg.wb.SetDebugSv("")
# while True:
# for i in range(0, 0x5b):
# pg.ad9512.Write(0x4A, 0x55)
# time.sleep(0.2)
# # print "[0x%02x]: 0x%02x" % (i, pg.ad9512.Read(0x4A))
......
......@@ -37,6 +37,7 @@ import time
import warnings
from WbOverlay import *
from DS18B20 import *
from AD9512 import *
from CommonFunctions import *
class Ffpg(object):
......@@ -47,6 +48,7 @@ class Ffpg(object):
inputClockFrequency = None # frequency (in MHz) of the selected clock
fineTriggerPhase = {1: 0, 2: 0} # individual for each channel, in [ns]
temp = None # DS18B20 OneWire temperature chip
ad9512 = None # AD9512 SPI
fmcSlot = None
def __init__(self, fmcSlot):
......@@ -55,6 +57,7 @@ class Ffpg(object):
self.fmcSlot = fmcSlot
self.wb = WbOverlay("fmc_fpg", fmcSlot)
self.temp = DS18B20(wbOverlay = self.wb)
self.ad9512 = AD9512(wbOverlay = self.wb, SpiBaseAddress = "SpiBase")
assert self.CompareVersion(1, 3, 0) == 0, "Bad gateware version detected! Get the appropriate driver from http://www.ohwr.org/projects/fmc-del-1ns-2cha/repository/revisions/master/show/sw"
def GetFmcSlot(self):
......
import time
import math
from WbOverlay import *
class Spi(object):
wb = None
debug = False
SpiBaseAddress = ""
SpiOffset = 0
SpiConfig = {}
def __init__(self, wbOverlay, SpiConfig, SpiBaseAddress, SpiOffset = 0):
"""
wbOverlay = instance of WbOverlay class
SpiConfig = SPI configuration
SpiBaseAddress = encoreio register name
SpiOffset = offset from SpiBaseAddress
"""
if (wbOverlay is not None) and (type(wbOverlay) is WbOverlay):
self.wb = wbOverlay
else:
raise Exception("wbOverlay has to be specified!")
if (SpiConfig["Channel"] >= 32) or (SpiConfig["Channel"] < 0):
raise Exception("Error: SPI Channel out of range")
elif (SpiConfig["CPol"] > 1) or (SpiConfig["CPol"] < 0):
raise Exception("Error: SPI CPol can be only 0 or 1")
elif (SpiConfig["CPha"] > 1) or (SpiConfig["CPha"] < 0):
raise Exception("Error: SPI CPha can be only 0 or 1")
elif (SpiConfig["LSB1st"] > 1) or (SpiConfig["LSB1st"] < 0):
raise Exception("Error: SPI LSB1st can be only 0 or 1")
elif (SpiConfig["Length"] >= 2**12) or (SpiConfig["Length"] < 0):
raise Exception("Error: SPI Length out of range")
elif (SpiConfig["HalfPeriod"] >= 2**16) or (SpiConfig["HalfPeriod"] < 0):
raise Exception("Error:SPI Half period out of range")
elif (SpiConfig["WaitTime"] >= 2**16) or (SpiConfig["WaitTime"] < 0):
raise Exception("Error: SPI Half period out of range")
self.SpiConfig = SpiConfig
self.SpiBaseAddress = SpiBaseAddress
self.SpiOffset = SpiOffset
def _debug(self, text):
if (self.debug):
print(text)
def _ReadStatus(self):
return self.wb.Read(self.SpiBaseAddress, Offset = self.SpiOffset+0)
def _WriteConfig1(self, data):
self.wb.Write(self.SpiBaseAddress, data, Offset = self.SpiOffset+1)
def _WriteConfig2(self, data):
self.wb.Write(self.SpiBaseAddress, data, Offset = self.SpiOffset+2)
def _WriteShiftOut(self, data):
self.wb.Write(self.SpiBaseAddress, data, Offset = self.SpiOffset+3)
def _ReadShiftIn(self):
return self.wb.Read(self.SpiBaseAddress, Offset = self.SpiOffset+4)
def SpiWaitForFree(self, MaxTries = 500):
SpiFree = False
Tries = 0
self._debug("SpiWaitForFree: ")
while SpiFree == False:
if self.debug:
sys.stdout.write('.')
sys.stdout.flush()
SpiStatusReg = self._ReadStatus()
SpiState = (SpiStatusReg/2**16)&0x7
SpiFree = SpiState==4 or SpiState==0
Tries = Tries + 1
if Tries > MaxTries:
raise Exception("SpiWaitForFree time-out!")
self._debug(" (%d tries)" % Tries)
def SpiAccess(self, Data):
if (Data < 0):
raise Exception("SPI data cannot be negative")
self.SpiWaitForFree()
LSB1st = self.SpiConfig["LSB1st"]
Length = self.SpiConfig["Length"]
Config1 = self.SpiConfig["CPol"]*2**31 + self.SpiConfig["CPha"]*2**30 + LSB1st*2**29 + self.SpiConfig["Channel"]*2**16 + Length
Config2 = self.SpiConfig["HalfPeriod"]*2**16 + self.SpiConfig["WaitTime"]
self._WriteConfig1(Config1)
self._WriteConfig2(Config2)
Cycles = int(math.ceil(Length/32.0))
ReadValue = 0
if not LSB1st:
if Length % 32: Data = Data<<(32-Length%32)
for i in range(Cycles):
if LSB1st:
DataToSend = Data%2**32
self._WriteShiftOut(DataToSend)
Data = Data/2**32
else:
DataToSend = Data/2**(32*(Cycles-i-1))
self._WriteShiftOut(DataToSend)
Data = Data%2**(32*(Cycles-(i+1)))
self.SpiWaitForFree()
PartialShift = self._ReadShiftIn()
if LSB1st:
if i == Cycles-1:
PartialShift = PartialShift>>(Cycles*32-Length)
ReadValue = ReadValue + (PartialShift<<(32*i))
else:
if i == Cycles-1:
Residual = Length-(Cycles-1)*32
ReadValue = (ReadValue<<Residual)+PartialShift
else:
ReadValue = (ReadValue<<32)+PartialShift
return ReadValue
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