readout_rm/readout_awg_rm.sv

446 lines
14 KiB
Systemverilog
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//FILE_HEADER-------------------------------------------------------
//FILE_NAME : readout_awg_rm.sv
//DEPARTEMENT : QuantumCTek-ASIC
//AUTHOR : Yunzhuo Zhang
//TIME : 2024.10.21
//*******************************************************************
//DESCRIPTION : awg reference model define
//*******************************************************************
//END_HEADER*********************************************************
//问题待解决:数据类型定义
//pulsewidth信号定义在mcu_reg中
`ifdef READOUT_AWG_RM
`define READOUT_AWG_RM
//import uvm_pkg::*;
import nco_dpi_pkg::*;
import hilbert_fir_dpi_pkg::*;
class readout_awg_rm extends uvm_component;
virtual rm_if rm_if; //clk和sync
uvm_blocking_get_export #(EZQ_readout_dac_item) dac_rm2scb_port; //wave输出给scoreboard
uvm_blocking_get_port #(mcu_item) mcu_get_port; //从mcu获取带时间戳的包包含cwtime
EZQ_readout_dac_item dac_item_pkt;
mcu_item mcu_item_pkt;
`uvm_component_utils(readout_awg_rm);
static int NUM_WAY = 8;
static int DATA_WIDTH = 16;
extern function new(string name,uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task run_phase(uvm_phase phase);
extern task wave_play( //根据cw获取波形数据
logic [5:0] wave_id,
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mem_out[$],
logic [15:0] wave_len;
logic [15:0]time_in,
logic [15:0]time_out
);
extern task wave_mode( //awg算法
logic clr_valid, //sync
logic clr_en, //cw_data[6]
logic [1 :0] mod_mode, //func_ctrl[1:0]
logic [31:0] fcw,
logic [15:0] phase, //phase[31:16]
logic [DATA_WIDTH*NUM_WAY-1:0] wave_in,
logic [DATA_WIDTH-1:0] wave_mod_out[NUM_WAY],
logic [15:0]time_in,
logic [15:0]time_out
);
extern task wave_amp(
logic [15:0] amplitude, //amp[31:16]
logic [DATA_WIDTH-1:0] wave_amp_in[NUM_WAY],
logic [DATA_WIDTH-1:0] wave_amp_out[NUM_WAY],
logic [15:0]time_in,
logic [15:0]time_out
);
extern task wave_mix(
logic mix_en , //~func_ctrl[2]
logic [DATA_WIDTH-1:0] wave_in[NUM_WAY],
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mix_out,
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mix_outb,
logic [15:0]time_in,
logic [15:0]time_out
);
/*
extern task pulse_generator_pump(
logic pulse_en ,
logic [15:0] delay,
logic [31:0] width,
logic inv_en ,
logic [15:0] pulse
);
*/
endclass
function readout_awg_rm::new(string name,uvm_component parent);
super.new(name,parent);
endfunction : new
function void readout_awg_rm::build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual rm_if)::get(this,"","rm_if",rm_if))
`uvm_fatal("CFGERR",{"virtual interface must be set for: ",get_full_name(),".vif"});
mcu_get_port = new("spi_get_port",this);
dac_rm2scb_port = new("dac_rm2scb_port",this);
endfunction
task readout_awg_rm::run_phase(uvm_phase phase);//main task
//cw
logic clk;
logic [31:0] cw_data;
logic sync;
//awg config signal
logic [31:0] mcu_timer,
logic [31:0] mcu_counter,
logic [31:0] pulse_width,
logic [31:0] amplitude,
logic [31:0] frequency,
logic [31:0] phase,
logic [31:0] loc_state,
logic [31:0] glb_state,
logic [31:0] feed_data,
//control signal
logic [31:0] command;
logic [31:0] func_ctrl;
logic [31:0] pump_ctrl;
logic [31:0] mark_ctrl;
//get wave_idx & wave
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mem_out[$];
//wave_mod output signal
logic [DATA_WIDTH-1:0] wave_mod_out[NUM_WAY];
//wave_amp output siganl
logic [DATA_WIDTH-1:0] wave_amp_out[NUM_WAY];
//wave_mix output siganl
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mix_out;
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mix_outb;
//wave_out queue
logic [DATA_WIDTH*NUM_WAY-1:0] wave_out_list[$];
logic [DATA_WIDTH*NUM_WAY-1:0] wave_outb_list[$];
//Pump & Mark signal
logic pump_trig;
logic mark_trig;
logic pump_delay;
logic mark_delay;
logic [15:0] pump_width;
logic [15:0] mark_width;
//时间戳mcu_item_pkt到来时继承pkt中的时间
logic [15:0] time_cw;
logic [15:0] time_play;
logic [15:0] time_mode;
logic [15:0] time_amp;
logic [15:0] time_mix;
// sync signal
sync = rm_if.sync;
//MCU packet
mcu_get_port.get(mcu_item_pkt);
time_cw = mcu_item_pkt.clock_cycle;
cw_data = mcu_item_pkt.cw_data;
pulse_width = mcu_item_pkt.pulse_width;//该信号通过MCU的packet传送
//AWG reg
frequency = reg_mems::awg_regfile.get("Frequency");
phase = reg_mems::awg_regfile.get("Phase");
amplitude = reg_mems::awg_regfile.get("Amplitude");
mcu_timer = reg_mems::awg_regfile.get("Timer");
mcu_counter = reg_mems::awg_regfile.get("Counter");
loc_state = reg_mems::awg_regfile.get("LOC_State");
glb_state = reg_mems::awg_regfile.get("GLB_State");
feed_data = reg_mems::awg_regfile.get("FEED_Data");
func_ctrl = reg_mems::awg_regfile.get("Function");
command = reg_mems::awg_regfile.get("Command");
pump_ctrl = reg_mems::awg_regfile.get("pump_ctrl");
mark_ctrl = reg_mems::awg_regfile.get("maker_ctrl");
//AWG functions
wave_play(
.wave_id(cw_data[5:0]),
.wave_mem_out(wave_mem_out),
.wave_len(wave_len)
.time_in(time_cw),
.time_out(time_play)
);
for(k=0;k<wave_len;k++)begin
wave_mode(
.clr_valid(sync),
.clr_en(cw_data[6]),
.mod_mode(func_ctrl[1:0]),
.fcw(frequency),
.phase(phase[31:16]),
.wave_in(wave_mem_out[k]),
.wave_mod_out(wave_mod_out)
.time_in(time_play),
.time_out(time_mode)
);
wave_amp(
.amplitude(amplitude[31:16]), //amp[31:16]
.wave_amp_in(wave_mod_out),
.wave_amp_out(wave_amp_out),
.time_in(time_mode),
.time_out(time_amp)
);
wave_mix(
.mix_en(~func_ctrl[2]) , //~func_ctrl[2]
.wave_in(wave_amp_out),
.wave_mix_out(wave_mix_out),
.wave_mix_outb(wave_mix_outb),
.time_in(time_amp),
.time_out(time_mix)
);
wave_out_list.push_back (wave_mix_out);
wave_outb_list.push_back(wave_mix_outb);
end
//send to scoreboard
dac_item_pkt.cycle = time_mix;
for (k=0;k<wave_len;k++)begin
dac_item_pkt.data_out0[k] = wave_out_list[k][0*DATA_WIDTH:1*DATA_WIDTH-1];
dac_item_pkt.data_out1[k] = wave_out_list[k][1*DATA_WIDTH:2*DATA_WIDTH-1];
dac_item_pkt.data_out2[k] = wave_out_list[k][2*DATA_WIDTH:3*DATA_WIDTH-1];
dac_item_pkt.data_out3[k] = wave_out_list[k][3*DATA_WIDTH:4*DATA_WIDTH-1];
dac_item_pkt.data_out4[k] = wave_out_list[k][4*DATA_WIDTH:5*DATA_WIDTH-1];
dac_item_pkt.data_out5[k] = wave_out_list[k][5*DATA_WIDTH:6*DATA_WIDTH-1];
dac_item_pkt.data_out6[k] = wave_out_list[k][6*DATA_WIDTH:7*DATA_WIDTH-1];
dac_item_pkt.data_out7[k] = wave_out_list[k][7*DATA_WIDTH:8*DATA_WIDTH-1];
dac_item_pkt.data_outb0[k]= wave_outb_list[k][0*DATA_WIDTH:1*DATA_WIDTH-1];
dac_item_pkt.data_outb1[k]= wave_outb_list[k][1*DATA_WIDTH:2*DATA_WIDTH-1];
dac_item_pkt.data_outb2[k]= wave_outb_list[k][2*DATA_WIDTH:3*DATA_WIDTH-1];
dac_item_pkt.data_outb3[k]= wave_outb_list[k][3*DATA_WIDTH:4*DATA_WIDTH-1];
dac_item_pkt.data_outb4[k]= wave_outb_list[k][4*DATA_WIDTH:5*DATA_WIDTH-1];
dac_item_pkt.data_outb5[k]= wave_outb_list[k][5*DATA_WIDTH:6*DATA_WIDTH-1];
dac_item_pkt.data_outb6[k]= wave_outb_list[k][6*DATA_WIDTH:7*DATA_WIDTH-1];
dac_item_pkt.data_outb7[k]= wave_outb_list[k][7*DATA_WIDTH:8*DATA_WIDTH-1];
end
//pump and mark signal
pump_trig = cw_data[8];
mark_trig = cw_data[9];
pump_delay = pump_ctrl[31:16];
mark_delay = mark_ctrl[31:16];
pump_width = func_ctrl[6] ? pulse_width[15:0] : pump_ctrl[15:0];
mark_width = func_ctrl[7] ? pulse_width[31:16] : mark_ctrl[15:0];
//pump和mark信号的输出时间、输出宽度和输出极性
if(pump_trig)begin
rm_if.pump_width = pump_width;
rm_if.pump_rm = ~func_ctrl[4];
rm_if.pump_time = time_cw + pump_delay;
end else begin
rm_if.pump_width = 0;
rm_if.pump_rm = func_ctrl[4];
rm_if.pump_time = 0;
end
if(mark_trig)begin
rm_if.mark_width = mark_width;
rm_if.mark_rm = ~func_ctrl[5];
rm_if.mark_time = time_cw + mark_delay;
end else begin
rm_if.mark_width = 0;
rm_if.mark_rm = func_ctrl[5];
rm_if.mark_time = 0;
end
endtask
task readout_awg_rm::wave_play(
logic [5:0] wave_id,
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mem_out[$],
logic [15:0] wave_len;
logic [15:0]time_in,
logic [15:0]time_out
);
logic [31:0] get_wave_idx_len;
logic [15:0] wave_addr;
logic [15:0] wave_len;
logic [DATA_WIDTH*NUM_WAY-1:0]wave_out[wave_len]; //wave_len个8*16bit数据
time_out = time_in + 16'd4;
reg_mems::env_indx_ram.get32bit({wave_id[5:0],2'b00},get_wave_idx_len); //获取wave地址和长度
wave_addr = {get_wave_idx_len[31:16],4'b0};
wave_len = get_wave_idx_len[15: 0];
$display("wave_addr and wave_len is %b %d",wave_addr,wave_len);
reg_mems::env_data_ram.get32bit(wave_addr,wave_out); //获取wave波形数据
foreach (wave_out[i])begin
wave_mem_out.push_back(wave_out[i]);
$display("wave %d is %b ",i,wave_out[i]);
end
endtask
task readout_awg_rm::wave_mode(
logic clr_valid, //sync
logic clr_en, //cw_data[6]
logic [1 :0] mod_mode, //func_ctrl[1:0]
logic [31:0] fcw,
logic [15:0] phase, //phase[31:16]
logic [DATA_WIDTH*NUM_WAY-1:0] wave_in,
logic [DATA_WIDTH-1:0] wave_mod_out[NUM_WAY],
logic [15:0]time_in,
logic [15:0]time_out
);
//hilbert signal
logic hilbert_en;
logic [DATA_WIDTH-1:0] hilbert_in[NUM_WAY];
real dpi_hilbert_out_i[NUM_WAY];
real dpi_hilbert_out_q[NUM_WAY];
logic [DATA_WIDTH-1:0] hilbert_out_i[NUM_WAY];
logic [DATA_WIDTH-1:0] hilbert_out_q[NUM_WAY];
//nco signal
logic loc_rst_n;
logic clr_en;
logic [63:0] result_cos;
logic [63:0] result_sin;
logic [63:0] result_acc;
logic [15:0] cos_list[$];
logic [15:0] sin_list[$];
//mod signal
logic iq_mod_en;
logic [DATA_WIDTH*2-1:0] iq_mod_data_i_temp;
logic [DATA_WIDTH-1:0] iq_mod_data_i[NUM_WAY];
// logic [DATA_WIDTH-1:0] iq_mod_data_q[NUM_WAY];
//inter signal
loc_rst_n = ((mod_mode[1:0] == 2'b01) | (mod_mode[1:0] == 2'b11));
hilbert_en = (mod_mode[1:0] == 2'b01) | (mod_mode[1:0] == 2'b10);
iq_mod_en = (mod_mode[1:0] == 2'b01);
//time_delay
if (mod_mode[1:0] == 2'b11) //nco out
time_out = time_in + 16'd8 + 16'd1;
else begin
if(hilbert_en & iq_mod_en) //iq_mod out
time_out = time_in + 16'd8 + 16'd2 + 16'd1;
else if(hilbert_en & !iq_mod_en) //hilbert out
time_out = time_in + 16'd8 + 16'd1;
else (!hilbert_en)//wave_mem out
time_out = time_in + 16'd1;
end
//NCO dpi
objhandle=DPI_nco_initialize(objhandle);
for (k=0;k<NUM_WAY-1;k++)begin
//DPI_nco_terminate(objhandle);
DPI_nco(objhandle,real(fcw),real(phase),real(clr_en),real(k*fcw),result_cos,result_sin,result_acc);
cos_list.push_back(shortint(result_cos));
sin_list.push_back(shortint(result_sin));
end
//hilbert dpi
for(k=0;k<NUM_WAY;k++)begin
hilbert_in[k] = wave_in[k*DATA_WIDTH:(k+1)*DATA_WIDTH-1]; //将128bit数据拆分为16bit*8
end
OBJhandle=DPI_hilbert_fir_initialize(OBJhandle);
//DPI_hilbert_fir_terminate(OBJhandle);
DPI_hilbert_fir(OBJhandle,real(hilbert_in),dpi_hilbert_out_i,dpi_hilbert_out_q);//输入输出均为数组
hilbert_out_i = shortint(dpi_hilbert_out_i);
hilbert_out_q = shortint(dpi_hilbert_out_q);
foreach (hilbert_out_i[index])
$display("hilbert_out_i is :%b",hilbert_out_i[index]);
foreach (hilbert_out_q[index])
$display("hilbert_out_q is :%b",hilbert_out_q[index]);
//mod
for(k=0;k<NUM_WAY;k++)begin
iq_mod_data_i_temp = hilbert_out_i[k]*cos_list[k]-hilbert_out_q[k]*sin_list[k];
iq_mod_data_i[k] = {iq_mod_data_i_temp[31],iq_mod_data_i_temp[29:15]};
if(iq_mod_data_i[k]>32767) iq_mod_data_i[k] = 32767;
if(iq_mod_data_i[k]<-32767) iq_mod_data_i[k] = -32767;
end
for(k=0;k<NUM_WAY;k++)begin
iq_mod_data_q_temp = hilbert_out_q[k]*cos_list[k]+hilbert_out_i[k]*sin_list[k];
iq_mod_data_q[k] = {iq_mod_data_q_temp[31],iq_mod_data_q_temp[29:15]};
if(iq_mod_data_q[k]>32767) iq_mod_data_q[k] = 32767;
if(iq_mod_data_q[k]<-32767) iq_mod_data_q[k] = -32767;
end
foreach (iq_mod_data_i[index])
$display("iq_mod_data_i is :%b",iq_mod_data_i[index]);
//mux
case(mod_mode)
2'b00 : wave_mod_out = hilbert_in;
2'b01 : wave_mod_out = iq_mod_data_i;
2'b10 : wave_mod_out = hilbert_out_q;
2'b11 : wave_mod_out = cos_list;
endcase
task readout_awg_rm::wave_amp(
logic [15:0] amplitude, //amp[31:16]
logic [DATA_WIDTH-1:0] wave_amp_in[NUM_WAY],
logic [DATA_WIDTH-1:0] wave_amp_out[NUM_WAY],
logic [15:0]time_in,
logic [15:0]time_out
);
time_out = time_in +16'd1;
logic [DATA_WIDTH*2-1:0]wave_amp_out_temp;
for(k=0;k<NUM_WAY-1;k++)begin
wave_amp_out_temp = wave_amp_in[k] * amplitude;
wave_amp_out[k] = {wave_amp_out_temp[31],wave_amp_out_temp[29:15]};
if(wave_amp_out[k]>32767) wave_amp_out[k] = 32767;
if(wave_amp_out[k]<-32767) wave_amp_out[k] = -32767;
end
endtask
task wave_mix(
logic mix_en , //~func_ctrl[2]
logic [DATA_WIDTH-1:0] wave_in[NUM_WAY],
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mix_out,
logic [DATA_WIDTH*NUM_WAY-1:0] wave_mix_outb,
logic [15:0]time_in,
logic [15:0]time_out
);
if(mix_en)
time_out = time_in +16'd1;
else
time_out = time_in;
for(k=0;k<NUM_WAY;k++)begin
wave_mix_out[k*DATA_WIDTH:(k+1)*DATA_WIDTH-1] = wave_in[k]^{1'b1, {DATA_WIDTH-1{1'b0}}};//unsign to sign
end
if(mix_en)
for(k=0;k<NUM_WAY;k++)begin
wave_mix_outb[k*DATA_WIDTH:(k+1)*DATA_WIDTH-1] = ~wave_mix_out[k*DATA_WIDTH:(k+1)*DATA_WIDTH-1]+1'b1;//unsign to sign
end else
for(k=0;k<NUM_WAY;k++)begin
wave_mix_outb[k*DATA_WIDTH:(k+1)*DATA_WIDTH-1] = wave_mix_out[k*DATA_WIDTH:(k+1)*DATA_WIDTH-1];
end
foreach (wave_mix_out[index])
$display("wave_mix_out is :%b",wave_mix_out[index]);
foreach (wave_mix_outb[index])
$display("wave_mix_outb is :%b",wave_mix_outb[index]);
endtask
`endif