//FILE_HEADER------------------------------------------------------- //FILE_NAME : readout_awg_rm.sv //DEPARTEMENT : QuantumCTek-ASIC //AUTHOR : Yunzhuo Zhang //TIME : 2025.4.10 //******************************************************************* //DESCRIPTION : awg reference model define //******************************************************************* //END_HEADER********************************************************* `ifndef READOUT_AWG_RM `define READOUT_AWG_RM `include "../testbench/refm/mcu_cw_item.sv" `include "../testbench/refm/nco_dpi/codegen/dll/nco_model/nco_dpi_pkg.sv" `include "../testbench/refm/hilbert_dpi/codegen/dll/hilbert_fir/hilbert_fir_dpi_pkg.sv" import nco_dpi_pkg::*; import hilbert_fir_dpi_pkg::*; class readout_awg_rm extends uvm_component; `uvm_component_utils(readout_awg_rm); virtual rm_if rm_if; //sync uvm_analysis_port #(EZQ_readout_dac_item) dac_rm2scb_port; uvm_blocking_get_port #(mcu_cw_item) mcu_get_port; bit [31:0] mcu_timer ; bit [31:0] mcu_counter ; bit [31:0] loc_state ; bit [31:0] glb_state ; bit [31:0] feed_data ; bit [31:0] wave_ctrl ; bit [31:0] amplitude ; bit [31:0] frequency ; bit [31:0] phase ; bit [31:0] command ; bit [31:0] func_ctrl ; bit [31:0] pump_ctrl ; bit [31:0] mark_ctrl ; bit [31:0] cw_data ; bit cw_valid ; mcu_cw_item cw_queue[$] ; bit [31:0] clock_cycle ; bit [31:0] awg_clock_cycle ; bit [15:0] env_len ; bit [31:0] ram_data[bit[31:0]]; bit [31:0] wr_data ; bit [31:0] wr_addr ; bit [31:0] dac_send_cnt ; bit [15:0]data_out_0[$]; bit [15:0]data_out_1[$]; bit [15:0]data_out_2[$]; bit [15:0]data_out_3[$]; bit [15:0]data_out_4[$]; bit [15:0]data_out_5[$]; bit [15:0]data_out_6[$]; bit [15:0]data_out_7[$]; bit [15:0]data_outb_0[$]; bit [15:0]data_outb_1[$]; bit [15:0]data_outb_2[$]; bit [15:0]data_outb_3[$]; bit [15:0]data_outb_4[$]; bit [15:0]data_outb_5[$]; bit [15:0]data_outb_6[$]; bit [15:0]data_outb_7[$]; 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 get_mcu_cw_item(); extern task get_spi_item(); extern task get_config_data(); extern task send_dac_item(); extern task awg_exe(); extern task if_pump_mark(); extern task hilbert_fir( input bit signed [15:0] hilbert_in[$], input bit [15:0] data_size, output bit signed [15:0] hilbert_out[$] ); 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::get_mcu_cw_item(); mcu_cw_item mcu_cw_item; forever begin mcu_get_port.get(mcu_cw_item); cw_data = mcu_cw_item.cw_data; cw_valid = mcu_cw_item.cw_valid; `uvm_info(get_type_name(),$sformatf("awg_mcu_cw_data = %0h,awg_mcu_cycle = %0h,awg_cw_valid = %h",cw_data,mcu_cw_item.clock_cycle,cw_valid),UVM_LOW) if(cw_valid)begin clock_cycle = mcu_cw_item.clock_cycle; cw_queue.push_back(mcu_cw_item); `uvm_info(get_type_name(),$sformatf("cw_queue_size = %0h",cw_queue.size()),UVM_MEDIUM) end end endtask task readout_awg_rm::get_spi_item(); forever begin @(wr_data or wr_addr) ram_data[wr_addr] = wr_data; `uvm_info(get_type_name(),$sformatf("wr_addr = %0h,wr_data = %0h",wr_addr,wr_data),UVM_LOW) end endtask task readout_awg_rm::get_config_data(); forever begin @(posedge `CLK); if(ram_data.exists(`AWG_MCU_TIMER))begin mcu_timer = ram_data[`AWG_MCU_TIMER]; end if(ram_data.exists(`AWG_MCU_COUNTER))begin mcu_counter = ram_data[`AWG_MCU_COUNTER]; end if(ram_data.exists(`AWG_LOC_STATE))begin loc_state = ram_data[`AWG_LOC_STATE]; end if(ram_data.exists(`AWG_GLB_STATE))begin glb_state = ram_data[`AWG_GLB_STATE]; end /* if(ram_data.exists(`AWG_FEED_DATA))begin feed_data = ram_data[`AWG_FEED_DATA]; end */ if(ram_data.exists(`WAVE_CTRL))begin wave_ctrl = ram_data[`WAVE_CTRL]; end if(ram_data.exists(`AMPLITUDE))begin amplitude = ram_data[`AMPLITUDE]; end if(ram_data.exists(`FREQUENCY))begin frequency = ram_data[`FREQUENCY]; end if(ram_data.exists(`PHASE))begin phase = ram_data[`PHASE]; end if(ram_data.exists(`AWG_COMMAND))begin command = ram_data[`AWG_COMMAND]; end if(ram_data.exists(`AWG_FUNC_CTRL))begin func_ctrl = ram_data[`AWG_FUNC_CTRL]; end if(ram_data.exists(`PUMP_CTRL))begin pump_ctrl = ram_data[`PUMP_CTRL]; end else begin pump_ctrl = 32'h10010; end if(ram_data.exists(`MARK_CTRL))begin mark_ctrl = ram_data[`MARK_CTRL]; end else begin mark_ctrl = 32'h10010; end end endtask task readout_awg_rm::send_dac_item(); EZQ_readout_dac_item dac_item_pkt; forever begin if(data_out_0.size()>`DAC_MON_CYCLE)begin dac_item_pkt = new(); dac_item_pkt.data_out0 = data_out_0[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_out1 = data_out_1[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_out2 = data_out_2[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_out3 = data_out_3[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_out4 = data_out_4[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_out5 = data_out_5[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_out6 = data_out_6[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_out7 = data_out_7[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_outb0 = data_outb_0[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_outb1 = data_outb_1[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_outb2 = data_outb_2[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_outb3 = data_outb_3[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_outb4 = data_outb_4[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_outb5 = data_outb_5[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_outb6 = data_outb_6[0+: `DAC_MON_CYCLE]; dac_item_pkt.data_outb7 = data_outb_7[0+: `DAC_MON_CYCLE]; // dac_item_pkt.delay_cycle = awg_clock_cycle; dac_rm2scb_port.write(dac_item_pkt); `uvm_info(get_type_name(),$sformatf("dac_send_cnt = %0h",dac_send_cnt),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_out_0[0+: `DAC_MON_CYCLE] = %0p",data_out_0[0+: `DAC_MON_CYCLE]),UVM_LOW) /* `uvm_info(get_type_name(),$sformatf("data_out_1 = %0p",data_out_1),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_out_2 = %0p",data_out_2),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_out_3 = %0p",data_out_3),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_out_4 = %0p",data_out_4),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_out_5 = %0p",data_out_5),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_out_6 = %0p",data_out_6),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_out_7 = %0p",data_out_7),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_outb_0 = %0p",data_outb_0),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_outb_1 = %0p",data_outb_1),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_outb_2 = %0p",data_outb_2),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_outb_3 = %0p",data_outb_3),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_outb_4 = %0p",data_outb_4),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_outb_5 = %0p",data_outb_5),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_outb_6 = %0p",data_outb_6),UVM_LOW `uvm_info(get_type_name(),$sformatf("data_outb_7 = %0p",data_outb_7),UVM_LOW) `uvm_info(get_type_name(),$sformatf("data_outb_7 = %0p",data_outb_7),UVM_LOW) */ data_out_0 = data_out_0[`DAC_MON_CYCLE : $]; data_out_1 = data_out_1[`DAC_MON_CYCLE : $]; data_out_2 = data_out_2[`DAC_MON_CYCLE : $]; data_out_3 = data_out_3[`DAC_MON_CYCLE : $]; data_out_4 = data_out_4[`DAC_MON_CYCLE : $]; data_out_5 = data_out_5[`DAC_MON_CYCLE : $]; data_out_6 = data_out_6[`DAC_MON_CYCLE : $]; data_out_7 = data_out_7[`DAC_MON_CYCLE : $]; data_outb_0 = data_outb_0[`DAC_MON_CYCLE : $]; data_outb_1 = data_outb_1[`DAC_MON_CYCLE : $]; data_outb_2 = data_outb_2[`DAC_MON_CYCLE : $]; data_outb_3 = data_outb_3[`DAC_MON_CYCLE : $]; data_outb_4 = data_outb_4[`DAC_MON_CYCLE : $]; data_outb_5 = data_outb_5[`DAC_MON_CYCLE : $]; data_outb_6 = data_outb_6[`DAC_MON_CYCLE : $]; data_outb_7 = data_outb_7[`DAC_MON_CYCLE : $]; dac_send_cnt++; end @(posedge `CLK); end endtask task readout_awg_rm::awg_exe(); //fid chandle objhandle = null ; chandle OBJhandle = null ; bit [31:0] zeros_len; //get wave_idx & wave bit [5 :0] wave_id ; bit [24:0] env_map_addr ; bit [31:0] env_idx ; bit [24:0] env_addr ; bit [24:0] env_addr_1 ; bit [24:0] env_addr_2 ; bit [24:0] env_addr_3 ; bit [`NUM_WAY*`DATA_WIDTH-1 :0] wave_out ; bit [31:0] wave_out_0 ; bit [31:0] wave_out_1 ; bit [31:0] wave_out_2 ; bit [31:0] wave_out_3 ; bit [127:0] wave_out_queue[$] ; int k ; //wave_mod output signal bit [1 :0] mod_mode ; bit loc_rst_n ; bit hilbert_en ; bit iq_mod_en ; bit clr_en ; bit mix_en ; int j ; bit [47:0] frequency_48; real nco_acc_out ; real nco_acc_in ; bit signed[15:0] nco_cos[`NUM_WAY-1 :0] ; bit signed[15:0] nco_sin[`NUM_WAY-1 :0] ; bit signed[15:0] nco_cos_queue[$] ; bit signed[15:0] nco_sin_queue[$] ; bit signed[15:0] hilbert_in[$]; bit signed[15:0] hilbert_out[$]; bit signed[15:0] iq_mod_data_i_queue[$]; bit signed[15:0] iq_mod_data_q_queue[$]; bit signed[31:0] iq_mod_data_i_temp ; bit signed[31:0] iq_mod_data_q_temp ; bit signed[31:0] i_mult_cos; bit signed[31:0] i_mult_sin; bit signed[31:0] q_mult_cos; bit signed[31:0] q_mult_sin; bit signed[15:0] iq_mod_data_i[`NUM_WAY-1 :0] ; bit signed[15:0] iq_mod_data_q[`NUM_WAY-1 :0] ; bit signed[15:0] wave_mod_out[$] ; //wave_amp output siganl bit [31:0] wave_amp_out_temp; bit [`DATA_WIDTH-1:0] wave_amp_out[`NUM_WAY-1 :0]; //wave_mix output siganl bit [`DATA_WIDTH-1:0] wave_mix_out[`NUM_WAY-1:0]; bit [`DATA_WIDTH-1:0] wave_mix_outb[`NUM_WAY-1:0]; //Pump & Mark signal //wait sync signal `uvm_info(get_type_name(),"awg wait sync_in",UVM_LOW) wait (`SYNC_IN); `uvm_info(get_type_name(),"awg sync_in come",UVM_LOW) forever begin wait(cw_valid == 1); `uvm_info(get_type_name(),$sformatf("awg_cw_data = %h,wave_ctrl = %h,func_ctrl = %h",cw_data,wave_ctrl,func_ctrl),UVM_LOW) //config signals mod_mode = func_ctrl[1:0]; clr_en = cw_data[6]; loc_rst_n = (mod_mode == 2'b01) | (mod_mode == 2'b11); hilbert_en = (mod_mode == 2'b01) | (mod_mode == 2'b10); iq_mod_en = (mod_mode == 2'b01); mix_en = ~func_ctrl[2]; `uvm_info(get_type_name(),$sformatf("mod_mode = %h,clr_en = %h",mod_mode,clr_en),UVM_LOW); `uvm_info(get_type_name(),$sformatf("loc_rst_n = %h,hilbert_en = %h,iq_mod_en = %h",loc_rst_n,hilbert_en,iq_mod_en),UVM_LOW); //////////////////////////////////////// //delay calculator /////////////////////////////////////// //wave_play : 3 //hilbert : 8 //nco : 11 //iq_mod+mux: 2 + 1 //amp : 1 //mix : 1 //awg_out to dac_if :3 awg_clock_cycle = clock_cycle + 3; //wave_play case(mod_mode) 2'b00 : awg_clock_cycle = awg_clock_cycle + 2 + 3; //hilbert_in 2'b01 : awg_clock_cycle = awg_clock_cycle + 8 + 2 + 1 + 2 + 3; //iq_mod 2'b10 : awg_clock_cycle = awg_clock_cycle + 8 + 1 + 2 + 3; //hilbert_q 2'b11 : awg_clock_cycle = awg_clock_cycle + 8 + 1 + 2 + 3; //nco_cos endcase `uvm_info(get_type_name(),$sformatf("mod_mode = %0h,awg_clock_cycle = %0h",mod_mode,awg_clock_cycle),UVM_LOW); zeros_len = awg_clock_cycle - data_out_0.size() - dac_send_cnt * `DAC_MON_CYCLE; `uvm_info(get_type_name(),$sformatf("data_out_0.size() = %0h",data_out_0.size()),UVM_LOW); for (int i = 0; i < zeros_len; i++)begin data_out_0.push_back(16'h8000); data_out_1.push_back(16'h8000); data_out_2.push_back(16'h8000); data_out_3.push_back(16'h8000); data_out_4.push_back(16'h8000); data_out_5.push_back(16'h8000); data_out_6.push_back(16'h8000); data_out_7.push_back(16'h8000); data_outb_0.push_back(16'h8000); data_outb_1.push_back(16'h8000); data_outb_2.push_back(16'h8000); data_outb_3.push_back(16'h8000); data_outb_4.push_back(16'h8000); data_outb_5.push_back(16'h8000); data_outb_6.push_back(16'h8000); data_outb_7.push_back(16'h8000); end `uvm_info(get_type_name(),$sformatf("dac_send_cnt = %0h,zeros_len = %0h,data_out_0.size() = %0h",dac_send_cnt,zeros_len,data_out_0.size()),UVM_LOW); ///////////////////////////////////////////// //AWG functions ///////////////////////////////////////////// //wave_play wave_id = cw_data[5 :0]; env_map_addr= 25'hA00000 + {wave_id,2'b00}; env_idx = ram_data.exists(env_map_addr) ? ram_data[env_map_addr] : 0; //get env_idx env_addr = 25'hB00000 + {env_idx[31:16],4'b0}; //start address env_len = env_idx[15:0]; //128bit -- 4'b0 `uvm_info(get_type_name(),$sformatf("env_map_addr = %h,env_idx = %h",env_map_addr,env_idx),UVM_LOW); `uvm_info(get_type_name(),$sformatf("env_addr = %h,env_len = %h",env_addr,env_len),UVM_LOW); for(k =0; k0 && pump_flag == 1 && mark_flag == 1)begin mcu_cw_item = cw_queue.pop_front(); wait_cycle = mcu_cw_item.clock_cycle; cw_data_if = mcu_cw_item.cw_data; pump_flag = 1'b0; mark_flag = 1'b0; pump_trig = cw_data_if[8]; mark_trig = cw_data_if[9]; `uvm_info(get_type_name(),$sformatf("pump_trig = %0h,mark_trig = %0h",pump_trig,mark_trig),UVM_LOW); `uvm_info(get_type_name(),$sformatf("wait_cycle = %0h,cw_data_if= 0%h",wait_cycle,cw_data_if),UVM_LOW); case (func_ctrl[1:0]) 2'b00 : align_del = 4'h0; 2'b01 : align_del = 4'ha; 2'b10 : align_del = 4'h8; 2'b11 : align_del = 4'h8; endcase pump_delay = pump_ctrl[31:16] + align_del + 2; //compare to cw_valid pump_width = pump_ctrl[15:0] + env_len; `uvm_info(get_type_name(),$sformatf("pump_delay = %0h,pump_width = %0h,align_del = %0h",pump_delay,pump_width,align_del),UVM_LOW); mark_delay = mark_ctrl[31:16] + 2; //compare to cw_valid mark_width = mark_ctrl[15:0]; `uvm_info(get_type_name(),$sformatf("mark_delay = %0h,mark_width = %0h",mark_delay,mark_width),UVM_LOW); end fork if(cnt == wait_cycle)begin repeat(pump_delay)begin rm_if.pump_rm = func_ctrl[4]; @(posedge `CLK); end repeat(pump_width)begin if(pump_trig)begin rm_if.pump_rm = ~func_ctrl[4]; @(posedge `CLK); end else begin rm_if.pump_rm = func_ctrl[4]; @(posedge `CLK); end end rm_if.pump_rm = 1'b0; pump_flag = 1; end //mark if(cnt == wait_cycle)begin repeat(mark_delay)begin rm_if.mark_rm = func_ctrl[5]; @(posedge `CLK); end repeat(mark_width)begin if(mark_trig)begin rm_if.mark_rm = ~func_ctrl[5]; @(posedge `CLK); end else begin rm_if.mark_rm = func_ctrl[5]; @(posedge `CLK); end end rm_if.mark_rm = 1'b0; mark_flag = 1; end if(cnt == wait_cycle)begin if(pump_delay + pump_width >= mark_delay + mark_width)begin repeat(pump_delay + pump_width)begin cnt++; rm_if.cnt = cnt; @(posedge `CLK); end end else begin repeat(mark_delay + mark_width)begin cnt++; rm_if.cnt = cnt; @(posedge `CLK); end end end join end endtask task readout_awg_rm::hilbert_fir( input bit signed[15:0] hilbert_in[$], input bit [15:0] data_size, output bit signed[15:0] hilbert_out[$] ); localparam COEFF_LEN = 33; bit signed [15:0] coeff [0:COEFF_LEN-1] = { 16'd0, -16'd69, 16'd0, -16'd202, 16'd0, -16'd471, 16'd0, -16'd950, 16'd0, -16'd1766, 16'd0, -16'd3213, 16'd0, -16'd6337, 16'd0, -16'd20648, 16'd0, 16'd20648, 16'd0, 16'd6337, 16'd0, 16'd3213, 16'd0, 16'd1766, 16'd0, 16'd950, 16'd0, 16'd471, 16'd0, 16'd202, 16'd0, 16'd69, 16'd0 }; bit signed [31:0] acc ; bit signed [31:0] mul; //conv `uvm_info(get_type_name(),$sformatf("hilbert_in_queue = %p",hilbert_in),UVM_LOW); `uvm_info(get_type_name(),$sformatf("coeff = %p,data_size = %0d",coeff,data_size),UVM_LOW); for (int i = 0; i < COEFF_LEN + data_size; i++) begin for (int j = 0 ; j <= i; j++)begin mul = coeff[i-j] * hilbert_in[j]; acc = acc + mul; // `uvm_info(get_type_name(),$sformatf("coeff[%0d-%0d] = %0d ,hilbert_in[%0d] = %0d",i,j,coeff[i-j],j,hilbert_in[j]),UVM_LOW); // `uvm_info(get_type_name(),$sformatf("mul = %0d, mul[31:16] = %0d,acc = %0d",mul,$signed(mul[31:16]),acc),UVM_LOW); end if(acc[31] == 1)begin if(acc[15:0] == 0)begin hilbert_out[i] = $floor(acc/32768); end else begin hilbert_out[i] = $floor(acc/32768)- 1; end end else begin hilbert_out[i] = $floor(acc/32768); end // hilbert_out[i] = $floor(acc/32768); `uvm_info(get_type_name(),$sformatf("acc = %0d ,acc[31:16] = %0d,hilbert_out = %0d",acc,$floor(acc/32768),hilbert_out[i]),UVM_LOW); acc = 32'b0; end `uvm_info(get_type_name(),$sformatf("hilbert_out = %p,hilbert_out.size() = %d",hilbert_out,hilbert_out.size()),UVM_LOW); hilbert_out = hilbert_out[16:COEFF_LEN + data_size-18]; `uvm_info(get_type_name(),$sformatf("hilbert_out = %p,hilbert_out.size() = %d",hilbert_out,hilbert_out.size()),UVM_LOW); endtask task readout_awg_rm::run_phase(uvm_phase phase); fork get_mcu_cw_item(); get_spi_item(); get_config_data(); awg_exe(); if_pump_mark(); send_dac_item(); join endtask `endif