This commit is contained in:
zhangyz 2024-11-01 17:15:26 +08:00
commit 652b4c1d1a
1 changed files with 446 additions and 0 deletions

446
readout_awg_rm.sv Normal file
View File

@ -0,0 +1,446 @@
//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