Sie sind auf Seite 1von 60

Camera Serial Interface

2 (CSI-2)
TOP
TEST
ENV SCOREBOARD REG APB ADAPTER
VSEQR

REGMODEL

MON SQR MON SOR MON SQR SQR

COV DRV COV DRV MON COV DRV DRV

PPI AGENT APB AGENT PIXEL AGENT CCI AGENT REG AGENT
PPI INTF APB INTF PIXEL INTF CCI INTF REG INTF
DUT
ENV

INSTANTIATIONS: ………
• csi2_vseqr vseqr;
• csi2_ppi_tx_agt ppi_agt;
• apb_master_agt apb_m_agt;
• pixel_rx_agt pixel_agt;
• csi2_scb scb;
• ral_sys_CSI2_MEM_MAP regmodel;
• reg2apb_adapter reg2apb;
• csi2_cci_slave_agt cci_agt;
• csi2_rx_reg_agt reg_agt ;
build_phase:
vseqr = csi2_vseqr::type_id::create("vseqr",this);
ppi_agt = csi2_ppi_tx_agt::type_id::create("ppi_agt",this);
apb_m_agt = apb_master_agt::type_id::create("apb_m_agt",this);
pixel_agt = pixel_rx_agt::type_id::create("pixel_agt",this);
scb = csi2_scb::type_id::create("scb",this);
reg2apb = reg2apb_adapter::type_id::create("reg2apb",this);
//Adaptor creation
cci_agt = csi2_cci_slave_agt::type_id::create("cci_agt",this);
reg_agt = csi2_rx_reg_agt::type_id::create("reg_agt",this);
if(regmodel == null) begin
regmodel =
ral_sys_CSI2_MEM_MAP::type_id::create("regmodel",this);
regmodel.build();
regmodel.lock_model();
end
connect_phase:
• ppi_agt.a_port.connect(scb.ppi_pkt_export);
• pixel_agt.a_port.connect(scb.pixel_pkt_export);
• cci_agt.agent_port.connect(scb.cci_pkt_export);
• apb_m_agt.a_port.connect(scb.apb_pkt_export);
• vseqr.ppi_sqr = ppi_agt.seqr;
• vseqr.reg_sqr = reg_agt.seqr;
• vseqr.cci_sqr = cci_agt.seqr;
• vseqr.apb_sqr = apb_m_agt.seqr;
• regmodel.default_map.set_sequencer(apb_m_agt.seqr,reg2apb); // connect ral
map to bus sequencer and adaptor
• regmodel.default_map.set_auto_predict(1); //enable auto prediction ON if you are
not implementing predictor
• vseqr.regmodel = this.regmodel;
• scb.regmodel = this.regmodel;
• cci_agt.regmodel = this.regmodel ;
• uvm_config_db#(ral_sys_CSI2_MEM_MAP)::set(this,"*","ral_sys_CSI2_MEM_MAP",
regmodel);
VIRTUAL SEQUENCER
TEST
APB AGENT
ENV
SQR APB
VIRTUAL VIRTUAL
SEQUENCE SEQUENCER CCI AGENT

SQR APB SQR APB SQR CCI

SQR CCI
SQR CCI PPI AGENT

SQR PPI SQR PPI


SQR PPI

SQR REG REG AGENT


SQR REG
SQR REG
REG AGENT
• Reg agent is used to invoke lane enable signal which intern has lane enable,lane
shutdown,lane error signals in its interface.
• We have HS-mode and escape mode
• AGENT includes driver and sequencer (seqr). This sequencer will take sequence
named as csi2_reg_seq →(addr, data, rd_w).
• vseqr.reg_sqr = reg_agt.seqr;
• csi2_reg_seq seq;

• `uvm_do_on_with(seq , reg_sqr ,{seq.s_addr ==3'b000 ; (vseq- default


_config_vseq telling to take this seq on reg_sqr)
seq.s_rd_w == 1 ;}) //Read using seq->seqr->drive

• In that sequence we randomize the sequence_item of type req which is from uvm
library.
CCI AGENT
Camera Control Interface (CCI)
• CCI is a two-wire, bi-directional, half duplex, serial interface for controlling the
transmitter.

• CCI is compatible with the fast mode variant of the I2C interface.

• CCI shall support 400kHz operation and 7-bit Slave Addressing.

• CCI is capable of handling multiple slaves on the bus. Multi-master mode is not
supported by CCI.

CSI2 Transmitter CSI2


Receiver
Cont.. Data Transfer Protocol
• The slave address in the CCI is 7-bit.

• The CCI supports


• 8-bit index with 8-bit data or
• 16-bit index with 8-bit data.
A basic CCI message consists of
1. START condition
2. slave address
3. read = 1 / write = 0 bit,
4. acknowledge from slave,
5. sub adress (index) for pointing at a register
inside the slave device,
6. acknowledge signal from slave,
7. A. in write operation data byte from
master,
8. acknowledge/negative acknowledge from
slave
9. STOP condition

7. In read operation data byte comes from slave


8. acknowledge/negative acknowledge from master
Cont…
Cont…
• task detect_start();

Cont.. •


`uvm_info(get_type_name(),"Begin of detect
start",UVM_LOW);
@(posedge m_vif.clk_50)
• task detect_stop();
• if(m_vif.sclk_out == 1 && m_vif.sda_out == 1) begin
• int j; //initially scl and sda should high
• `uvm_info(get_type_name(),"Begin of detect • end
stop",UVM_LOW);
• else begin
• forever begin
• `uvm_fatal(get_type_name()," start condition is violated");
• @(posedge m_vif.clk_50);
• end
• if(m_vif.sclk_out == 1 && m_vif.sda_out == 0) begin
• forever begin
• //`uvm_info("INFO" , "Waiting for stop condition",
UVM_LOW); • @(posedge m_vif.clk_50)
• end • if(m_vif.sclk_out == 1 && m_vif.sda_out == 1) begin
• if(m_vif.sclk_out == 1 && m_vif.sda_out == 1) begin • // `uvm_info("INFO" , "Waiting for start condition drv",
UVM_LOW);
• `uvm_info(get_type_name(),"Stop detected",
UVM_LOW); • end
• out_of_reset = 0; • if(m_vif.sclk_out == 1 && m_vif.sda_out == 0) begin
• `uvm_info(get_type_name(),"End of detect • `uvm_info(get_type_name(),"Start detected",
stop",UVM_LOW); UVM_LOW);
• return; • `uvm_info(get_type_name(),"End of detect
start",UVM_LOW);
• end
• return;
• end
• end
• endtask
Cont..
• task drive_ack();
• int i;
• for(i = 0; i < 160; i++) begin
• @(posedge m_vif.clk_50);
• end
• if(m_vif.sda_en == 0 && item.nack_en == 1) begin
• m_vif.tb_sda_out <= 1;
• end
• else if(m_vif.sda_en == 0 && item.nack_en == 0) begin
• m_vif.tb_sda_out <= 0;
• end
• else begin
• `uvm_info(get_type_name(),
• "sda_en should be pulled low to drive
ack",UVM_LOW);
• end
• endtask
Cnt..
• task write_data();
• task read_data();
• `uvm_info(get_type_name(),"Begin of write
• bit [7:0] temp;
data",UVM_LOW);
• int i,j; • get_address(); //Simply wait for 8 clock cycle as MASTER is
• `uvm_info(get_type_name(),"Begin of read data", transmiting data from DATA reg
UVM_LOW);
• drive_ack();
• /*--------- Repeats loop for number of bytes -----------------*/
• `uvm_info(get_type_name(),"End of write data",UVM_LOW);
• temp = item.data;
• endtask
• for(i = 7; i >= 0; i--) begin
• task get_address();
• for (j = 0; j< 160; j++) begin
• int i,j;
• @(posedge m_vif.clk_50);
• for(i = 7; i >= 0; i--) begin
• end
• for (j = 0; j< 160; j++) begin
• m_vif.tb_sda_out <= temp[i];
• @(posedge m_vif.clk_50);
• end
• end
• /*---- Waiting for next clock cycle and checks ack --------*/
• end
• for (j = 0; j< 160; j++) • endtask
• @(posedge m_vif.clk_50);
• `uvm_info(get_type_name(),"End of read data",UVM_LOW);
• endtask
Starting.. • for (j = 0; j< 160; j++) begin // 8th clock blank
• data=regmodel.CSI2_RX_ADDR_BLK.CCI_CONTROL_REG. • @(posedge m_vif.clk_50);
get(); • end
• @(posedge m_vif.sclk_out)
• drive_ack(); // drive ack from SLAVE
side
• item.slave_addr[6] = m_vif.sda_out; //MSB transmit • item.index_addr_en = data[3:2]; //Uses read
first data from the control register
• item.rd_wr = data[1];
• /*----------------- Getting slave address --------------------
*/ • item.byte_cnt = data[7:4];
• for( i = 5; i >= 0; i--) begin • item.rep_start = data[8];
• for (j = 0; j< 160; j++) begin
• @(posedge m_vif.clk_50);
• end
• item.slave_addr[i] = m_vif.sda_out;
• end
Cnt..
• /*--------------- Write loop - Random location ---------------*/

• if(item.rd_wr == 0 && item.rep_start == 0 &&


• /*--------------- Write loop - Random location -------------
• (item.index_addr_en == 2 || item.index_addr_en == 3)) --*/
begin
• /*--------- Loop to get second 8-bit index address -------
• `uvm_info(get_type_name(),"Inside write data -*/
loop",UVM_LOW);
• for(i = 7;i >= 0;i--) begin
• m_vif.tb_sda_en <= item.rd_wr;
• for (j = 0; j< 160; j++) begin
• /*--------- Loop to get first 8-bit index address ---------*/
• @(posedge m_vif.clk_50);
• for(i = 7;i >= 0;i--) begin
• end
• for (j = 0; j< 160; j++) begin
• item.sub_addr2[i] = m_vif.sda_out;
• @(posedge m_vif.clk_50);
• end • end

• item.sub_addr1[i] = m_vif.sda_out; • /*---------------- Waiting to drive ack ------------------


-*/
• end • drive_ack();
• /*---------------- Waiting to drive ack -------------------*/ • repeat(item.byte_cnt) begin
• drive_ack(); • write_data();
• end
• end
Cnt.
/*-------------- Read loop- 8bit index address ---------------*/ /*---------------- Waiting to drive ack -------------------*/
else if(item.rd_wr == 1 && item.index_addr_en == 1 && drive_ack();
item.rep_start == 1) begin /*-------------- Loop to drive read data ------------------*/
`uvm_info(get_type_name(), if(m_vif.tb_sda_en) begin
"Inside read data loop 8bit index address",UVM_LOW); repeat(item.byte_cnt - 1) begin
/*--------- Loop to get first 8-bit index address ---------*/ read_data();
for(i = 7;i >= 0;i--) begin
if(m_vif.sda_en == 1 && m_vif.sda_out == 0) begin
for (j = 0; j< 160; j++) begin
@(posedge m_vif.clk_50); `uvm_info(get_type_name(), "Ack received from
end DUT",UVM_LOW);
item.sub_addr1[i] = m_vif.sda_out; end
end else begin
m_vif.tb_sda_en <= item.rd_wr; `uvm_error(get_type_name(),"NACK driven inbetween
/*---------------- Waiting to drive ack -------------------*/ read");
drive_ack();
end
/*--------------- Loop to get slave address ---------------*/
for(i = 6; i >= 0; i--) begin end
for (j = 0; j< 160; j++) begin read_data();
@(posedge m_vif.clk_50); if(m_vif.sda_en == 1 && m_vif.sda_out == 1)
end `uvm_info(get_type_name(), "NACK driven",UVM_LOW);
item.slave_addr[i] = m_vif.sda_out; end
end else begin
for (j = 0; j< 160; j++) begin
`uvm_error(get_type_name(),"Read enable is wrong");
@(posedge m_vif.clk_50);
end end
end
PPI AGENT
LOW LEVEL PROTOCOL

LANE MANAGMENT

D-PHY LAYER
PPI Signals
Low Level Protocol
Cont…
• The Low Level Protocol (LLP) is a byte orientated, packet based protocol
• Supports two packet structures
• Long packets
• Short packets.

• Low Level Protocol Features:


• 8-bit word size
• Support for up to four interleaved virtual channels on the same link
• Special packets for frame start, frame end, line start and line end
information
• Descriptor for the type, pixel depth and format of the Application
Specific Payload data
• 16-bit Checksum Code for error detection.
• 8-bit Error Correction Code for error detection and correction (D-PHY
physical layer only)
Low Level Protocol Packet Format
Cont…

For each packet structure,


start of the packet : exit from the low power state followed by the Start of
Transmission (SoT) sequence
end of the packet : The End of Transmission (EoT) sequence followed by
the low power state
Low Level Protocol Long Packet Format D-PHY
Cont…
• A Long Packet shall be identified by Data Types 0x10 to 0x37
Low Level Protocol Short Packet Format
Cont…
• A Short Packet shall be identified by Data Types 0x00 to 0x0F.

• A Short Packet shall contain only a Packet Header; neither Packet Footer nor
Packet Filler bytes shall be present.

Short Packet Data Field


• For Frame Synchronization Data Types : the frame number
• For Line Synchronization Data Types : the line number
• For Generic Short Packet Data Types : user defined
Cnt..
• typedef enum bit[5:0] {FS = 6'h00,FE = 6'h01,LS = 6'h02,LE
= 6'h03,RS_SP_1, • // Enumerated data type for ECC error Generation
• RS_SP_2,RS_SP_3,RS_SP_4,G_SP1 = and Distribution
6'h08,G_SP2 = 6'h09, • typedef enum bit[1:0] { ECC_NO_ERR =
• G_SP3 = 6'h0A,G_SP4 = 6'h0B,G_SP5 = 2'b00,ECC_1B_ERR = 2'b01,
6'h0C,G_SP6 = 6'h0D,
• ECC_2B_ERR = 2'b10,ECC_3B_ERR =
• G_SP7 = 6'h0E,G_SP8 = 6'h0F,NULL = 2'b11} ecc_er_enu;
6'h10,BLKNG = 6'h11,

• ED =
6'h12,RS_LP_1,RS_LP_2,RS_LP_3,RS_LP_4,RS_LP_5, • // Enumerated data type for CRC error Generation
and Distribution

RS_LP_6,RS_LP_7,RS_LP_8,RS_LP_9,RS_LP_10,RS_LP_11, • typedef enum bit { NO_CRC_ERR = 1'b0,CRC_ERR
• YUV422 =
= 1'b1} crc_er_enu;
6'h1E,RS_LP_12,RS_LP_13,RS_LP_14,
• RGB565 = 6'h22,RS_LP_15,RGB888 = • // Enumerated data type for Word Count error
6'h24,RS_LP_16, Generation and Distribution
• RS_LP_17,RS_LP_18,RAW6 =
6'h28,RS_LP_20,RAW8 = 6'h2A, • typedef enum bit[1:0] { NO_WC_ERR =
2'b00,INC_WC_ERR = 2'b01,
• RAW10 =
6'h2B,RS_LP_21,RS_LP_22,RS_LP_23,RS_LP_24, • DEC_WC_ERR = 2'b11}
wc_er_enu;
• UD1 = 6'h30,UD2 = 6'h31,UD3 = 6'h32,UD4 =
6'h33,

RS_LP_25,RS_LP_26,RS_LP_27,RS_LP_28,RS_LP_29,RS_LP_
30,

RS_LP_31,RS_LP_32,RS_LP_33,RS_LP_34,RS_LP_35,
• RS_LP_36} ftyp_enu;

cnt.
typedef enum bit[5:0] {FS = 6'h00,FE = 6'h01,LS = 6'h02,LE = rand bit crc_err_en ; // Enabling CRC error generation
6'h03,RS_SP_1, rand bit dphy_err_en ; // Enabling CRC error generation
// Enumerated Data type for Rs Active to sync delay Distribution. rand bit wc_err_en ; // Enabling Word count error generation
typedef enum { rand bit [4:0] wc_err_val ; // Word count error
V_SMALL_D,SMALL_D,MEDIUM_D,LARGE_D,V_LARGE_D} a2s_dy_enu; increment/decrement value.
// Enumerated Data type for LP signals delay Distribution. rand bit [15:0] max_bytcnt ; // Max byte count for the received pkt.
typedef enum { LP_ZERO_D, rand bit [4:0] ecc_err_pos ; // the bit position of error in Packet
LP_V_SMALL_D,LP_SMALL_D,LP_MEDIUM_D,LP_LARGE_D,LP_V_LARGE_D // Header in the case of 1-bit error in ECC.
} lp_delay_enu; rand a2s_dy_enu a2s_dl_e ; // enumerated data for ack2sync dly
// distribution.
typedef enum { LOW,HIGH,RAND } speedtyp_enu; rand int act2sync_dly ; // random delay to specify the delay in
class csi2_llp_pkt_txd extends uvm_sequence_item; // terms of clock between RXActive_HS and
rand ftyp_enu dt_e ; // data type identifier // RS_sync_HS Signals.
rand bit [1:0] vc_no ; // virtual channel number rand bit [27:0] err_data ; //Error Data for DPHY errors.
rand bit [15:0] wc ; // word count (LP) / number(SP) rand speedtyp_enu speedtyp_e ; // Enumerated field for SPEED type
bit [7:0] ecc ; // 8-bit Error Correction Code rand bit lp_mode_active ; // Flag to know the mode of operation
// for Packet Header(vc_no+dt+wc) // Constrained based on speed type
rand bit [7:0] pyld_q[$] ; // payload queue to store the data rand lp_delay_enu lpdt2data_dly_e ; // Enumerated field for
bit [15:0] crc ; // 16-bit crc for the payload queue entries. lpdt2data_dly distribution.
rand ecc_er_enu ecc_ertyp_e ; // enumerated data type for ECC rand int unsigned lpdt2data_dly ; // Random delay to specify the delay
Error in
// distribution // terms of clock between rxlpdt_esc and
rand crc_er_enu crc_ertyp_e ; // enumerated data type for CRC Error // esc_data signals
// distribution rand lp_delay_enu lp_dat2dat_dly_e; // Enumerated field for
rand wc_er_enu wc_ertyp_e ; // enumerated data type for Word lp_data2data_dly distribution.
Count rand int unsigned lp_data2data_dly; // Random delay to specify the
// Error distribution delay in
rand bit ecc_err_en ; // Enabling ECC error generation // terms of clock between each byte of esc data GO
Low Level Protocol Packet Format
Cont…
• For both physical layer options,
• the 8-bit Data Identifier field defines the Virtual Channel for the data and the Data
Type for the application specific payload data.
• the 16-bit Word Count (WC) field defines the number of 8-bit data words in the Data
Payload between the end of the Packet Header and the start of the Packet Footer.
• No Packet Header, Packet Footer, or Packet Filler bytes shall be included in the
Word Count.

• For the D-PHY physical layer option,


• the Error Correction Code (ECC) byte allows single-bit errors to be corrected
• 2-bit errors to be detected in the Packet Header. This includes both the Data
Identifier value and the Word Count value.
Low Level Protocol Short Packet Format
Cont…

Data Identifier (DI)

Virtual Channel Identifier Data Type (DT)

• To provide separate channels for • specifies the format and content


different data flows that are interleaved of the payload data.
in the data stream • A maximum of sixty-four data
• A maximum of four data streams is types are supported.
supported • There are eight different data
• valid channel identifiers are 0 to 3. type classes .
• The virtual channel identifiers in the Within each class there are
peripherals should be programmable up to eight different data type
to allow the host processor to control definitions.
how the data streams are de-
multiplexed.
Low Level Protocol Short Packet Format
Cont…
Virtual Channel Identifier(VC)
Low Level Protocol Short Packet Format
Cont…
Data Type (DT)
Packet Header Error Correction Code for D-PHY
Cont…
• Packet Header Error Correction Code (ECC) byte allows
• D-PHY physical layer option
• single-bit errors in the data identifier and the word count to be corrected
• two-bit errors to be detected
• C-PHY physical layer option
• ECC is not available

24-bit subset of the code shall be used.


Therefore,
bits 7 and 6 of the ECC byte shall be zero
Hamming-Modified Code
Cont… • Each syndrome in the matrix is MSB left aligned:

e.g. 0x07=0b0000_0111=P7P6P5P4P3P2P1P0

• The top row defines the three LSB of data position bit, and
the left column defines the three MSB of data position bit (there are 64-bit positions in total).

• e.g. 37th bit position is encoded 0b100_101 and has the syndrome 0x68.

• To derive the parity P0 for 24-bits, the P0’s in the orange rows will define if the corresponding bit
position is used in P0 parity or not.

e.g. P024-bits = D0^D1^D2^D4^D5^D7^D10^D11^D13^D16^D20^D21^D22^D23

• To correct a single-bit error, the syndrome has to be one of the syndromes Table 4, which will identify
the bit position in error.

• The syndrome is calculated as:


S = PSEND^PRECEIVED
where PSEND is the 8/6-bit ECC field in the header and
PRECEIVED is the 681 calculated parity of the received header.
Cnt..
• // function to calculate ECC
• function void calc_ecc();
• bit [31:0] hdr;

• // The Packet header is formed by concatenating • this.ecc[4] = hdr[4] ^ hdr[5] ^ hdr[6] ^ hdr[7] ^
• // word count,virtual channel number and data type identifier.
hdr[8] ^ hdr[9] ^
• hdr = {8'h00,this.wc,this.vc_no,this.dt_e}; //assume initially the • hdr[16] ^ hdr[17] ^ hdr[18] ^ hdr[19] ^
MSB 8 bit ECC is 0 hdr[20] ^ hdr[22] ^

• hdr[23] ;
• // ECC field is updated by XOR-ing the values of the header
• // as specified by the ECC Syndrome Assosiation matrix.
• this.ecc[5] = hdr[10] ^ hdr[11] ^ hdr[12] ^
hdr[13] ^ hdr[14] ^ hdr[15] ^
• this.ecc[0] = hdr[0] ^ hdr[1] ^ hdr[2] ^ hdr[4] ^ hdr[5] ^
hdr[7] ^ • hdr[16] ^ hdr[17] ^ hdr[18] ^ hdr[19] ^
• hdr[10] ^ hdr[11] ^ hdr[13] ^ hdr[16] ^ hdr[20] ^ hdr[21] ^ hdr[22] ^
hdr[21] ^
• hdr[22] ^ hdr[23] ; • hdr[23];
• this.ecc[1] = hdr[0] ^ hdr[1] ^ hdr[3] ^ hdr[4] ^ hdr[6] ^
hdr[8] ^
• this.ecc[6] = 1'b0;
• hdr[10] ^ hdr[12] ^ hdr[14] ^ hdr[17] ^ hdr[20] ^ • this.ecc[7] = 1'b0;
hdr[21] ^
• hdr[22] ^ hdr[23] ;
• this.ecc[2] = hdr[0] ^ hdr[2] ^ hdr[3] ^ hdr[5] ^ hdr[6] ^ • // since error can also be introduced in the
hdr[9] ^ syndrome, the syndrome is
• hdr[11] ^ hdr[12] ^ hdr[15] ^ hdr[18] ^ hdr[20] ^
hdr[21] ^ • // added to the hdr before inverting.
• hdr[22] ;
• this.ecc[3] = hdr[1] ^ hdr[2] ^ hdr[3] ^ hdr[7] ^ hdr[8] ^
hdr[9] ^ • hdr = {this.ecc,this.wc,this.vc_no,this.dt_e};
• hdr[13] ^ hdr[14] ^ hdr[15] ^ hdr[19] ^ hdr[20] ^
hdr[21] ^
Cnt.. •


// If there is 2-bit ecc error ,
// then the 8 and 18 bits of header are negated.
• else if(this.ecc_ertyp_e == ECC_2B_ERR ) begin
• hdr[3] = !hdr[3] ;
• // If there is 3-bit ecc error , • hdr[7] = !hdr[7] ;
• // then the 2,5 and 7 bits of header • end
are negated. •
• if(this.ecc_ertyp_e == ECC_3B_ERR • // If there is 1-bit ecc error , then the bit
) begin • // ,based on the value of ecc_err_pos, of header is negated.
• hdr[2] = !hdr[2]; • else if(this.ecc_ertyp_e == ECC_1B_ERR )
• hdr[3] = !hdr[3]; • hdr[this.ecc_err_pos] = !hdr[this.ecc_err_pos] ; //Here the
ecc_err_pos is random value when driver drive
• hdr[7] = !hdr[7];
• end • // The changes in the packet header fields are updated
• • // depending on the scenario of errors.
• {this.ecc,this.wc,this.vc_no} = hdr[31:6] ;
• this.dt_e = ftyp_enu'(hdr[5:0]); //Based on the new
Header update the ecc,wc,vc_no and dt_e

• endfunction
Cont…

Lane management
• The CSI-2 transmitter incorporates a Lane Distribution Function (LDF)
which accepts a sequence of packet bytes from the low level protocol
layer and distributes them across N Lanes, where each Lane is an
independent unit of physical-layer logic (serializers, etc.) and
transmission circuitry. The CSI-2 receiver incorporates a Lane
Merging Function (LMF) which collects incoming bytes from N Lanes
and consolidates (merges) them into complete packets to pass into
the packet decomposer in the receiver’s low level protocol layer.
Cont…

LDF
Cont..
• // the do_pack() function packs the fields of the LLP packet,based on the
• // type of the packet, to array of bytes.
• function void do_pack(uvm_packer packer);
• super.do_pack(packer);
• packer.pack_field_int(dt_e,$bits(dt_e));
• packer.pack_field_int(vc_no,$bits(vc_no));
• packer.pack_field_int(wc,$bits(wc));
• packer.pack_field_int(ecc,$bits(ecc));
• //if(this.dt_e[5:4] != 2'b00 || pyld_q.size() != 0 ) begin
• if(pyld_q.size() != 0 ) begin
• foreach(pyld_q[i]) packer.pack_field_int(pyld_q[i],8 );
• packer.pack_field_int(crc,$bits(crc));
• end
• endfunction

LMF
Cnt..
• // the do_u // the LLP packet,based on the type of the packet.
• function void do_unpack(uvm_packer packer);
• super.do_unpack(packer);
• this.dt_e = ftyp_enu'(packer.unpack_field_int($bits(dt_e)));
• this.vc_no = packer.unpack_field_int($bits(vc_no));
• this.wc = packer.unpack_field_int($bits(wc));
• this.ecc = packer.unpack_field_int($bits(ecc));
• this.check_ecc();
• // The payload and crc is unpacked for long packets .

• if(this.ecc_ertyp_e != ECC_2B_ERR && this.ecc_ertyp_e != ECC_3B_ERR &&
• this.dt_e[5:4] != 2'b00 ) begin
• for(int i = 0;i < ((packer.get_packed_size()/8)-6); i++ ) //get_packed_size() gives total no of bits packed.
• //divide by 8 gives no of bytes. again deducting 6 indicates 4 byte
HEADER //and 2 byte CRC
• this.pyld_q.push_back(packer.unpack_field_int(8));

• this.crc = packer.unpack_field_int($bits(crc));
• end
• endfunctionnpack() function unpacks the array of bytes to the fields of
Cont…
• This task get the packet from sequencer.
• Calculates ecc and crc. Then pack the packet using pack_bytes function.
• Calculates packed array size and calls drive_pkt task.
• If(pkt)
• if(shrt_pkt && 2-bit error) begin
• Update status registers
• Calling ecc and crc functions
• Packing variables into an array
• DRIVE_PCKT();
DRIVE_PKT
• HERE will check for modes with lp_mode_active signal .If high means LP-mode
and low means HS mode. While transforming one mode to another mode wait
for shutdown time and make previous mode low.
• Based on number of lines we select method and drive all lanes parllely.
• Based on the configured number of lanes, it calculates the loop cnt.
• From pkd_bytes array, it takes the data corresponding to lane_0 and drives the
data in lane_0 according to protocol.
Cnt..
• virtual task drive_lane_2();
• int lp_cnt;
• if (pkt_array_size % no_of_lanes >
2) begin
• lp_cnt =
(pkt_array_size/no_of_lanes) + 1;
• end else begin
• lp_cnt =
(pkt_array_size/no_of_lanes);
• end
• if(!lp_mode_active)
• drive_hs_lane_2(lp_cnt);
• else
• drive_lp_lane_2(lp_cnt);
• endtask
Cnt..
Cnt..
• task drive_hs_lane_2(int lp_cnt); • m_vif.rx_sync_hs_2 <= 'b1;
• int indx = 2; //For lane- • @(posedge m_vif.rx_byteclk_hs_2);
2, data transfer starts at index=2
• if (m_vif.reset_n) begin
• if(lp_mode_active != prev_speed)
begin • m_vif.rx_sync_hs_2 <= 'b0;
• repeat(hs_startup_time) • m_vif.rx_valid_hs_2 <= 'b1;
• @(posedge • end
m_vif.rx_byteclk_hs_2);
• for (int i = 0; i < lp_cnt; i ++) begin
• end
• @(posedge m_vif.rx_byteclk_hs_2); • if (!m_vif.reset_n) break;
• if (m_vif.reset_n) begin • if (i != 0) begin
• m_vif.rx_active_hs_2 <= 'b1; • @(posedge
m_vif.rx_byteclk_hs_2);
• end
• end
• repeat (active_to_sync_dly) begin
• @(posedge m_vif.rx_byteclk_hs_2); • m_vif.rx_data_hs_2 <=
pkd_bytes[indx];
• if (!m_vif.reset_n) break;
• indx = indx + no_of_lanes;
• end
• end;
PPI
• For a PHY with multiple Data Lanes, a set of PPI signals is used for each Lane.
Each signal has been assigned into one of six categories: High-Speed transmit
signals, High-Speed receive signals, Escape mode transmit signals, Escape mode
receive signals, control signals, and error signals.
HS-MODE Pn

DIGITAL ANALOG
Cn
CAMERA

Pn

DIGITAL ANALOG
DISPLAY Cn
GO
Hs-mode
PIXEL AGENT
PIXEL
• Pixel monitor receives the data (dut) from pixel interface. Inside pixel
Monitor we have frame start, frame end, line start, line end, short
packet and data.
capture_fr_start();
capture_fr_end();
capture_ln_start();
capture_ln_end();
capture_sh_pkt();
data_capture();
Cont…..
• capture_fr_start();
• Insede the frame start task we are randomize as the data type must be FS like wise
• packet.randomize() with { vc_no == m_vif.pixel_channel_no;
• dt_e == FS;
• wc == m_vif.pixel_word_cnt;
• ecc_err_en == 1'b0;
crc_err_en == 1'b0;
• wc_err_en == 1'b0;
• wc_err_val == 5'b0;
• dphy_err_en == 1'b0;
• ecc_err_pos == 1'b0;
• };
Cont…
• After randomizing according to the frame start or frame end or line start or
line end --- calculate the ecc for that
• packet.calc_ecc();
• Send the data of frame start or frame end or line start or line end to the
scoreboard through sequence item csi2_llp_pkt_txd(packet)
• send_2_aport(packet);
• After sending to the scoreboard get the data from the regmodel.
• if(regmodel.CSI2_RX_ADDR_BLK.ECC_Enable.get())
• frm_cntr++;
ECC_Enable Indicates ECC has performed on the received packet header
Cont….
• For the short packet
• if(m_vif.short_pkt_valid == 1 && m_vif.pixel_data_type[5:4] == 2'b00
&& !m_vif.frame_start && !m_vif.frame_end && !m_vif.line_start
&& !m_vif.line_end ) begin
• In data_capture() task we are collect the data from dut
• pixel_q.push_back(m_vif.pixel_data);
• based on the dt_type start reading byte from the pixel queue
• pixel_byt_conv(pixel_q,payld_q,ftyp_enu'(m_vif.pixel_data_type),m_
vif.pixel_word_cnt);
Cont….
• case(dt_type)
• RGB888 : begin
• bytpr_p = 3;//RGB888
• n_byt = 3;
• end
• RGB565 : begin
• bytpr_p = 4;//RGB565
• n_byt = 2;
• end
• RAW10 : begin
• bytpr_p = 5;//RAW10
• n_byt = 5;
• end
Cont…..
• if RAW10 the byte conversion is different the LSB's are rearranged to push into the payload queue
• if(dt_type == 6'h2B) begin (for RAW10 data type)
• the first four pixel byte are directly pushed into the queue
• for(int j = 9;j<= bytpr_p*8-1 ;j=j+10) begin
• payld_q.push_back(pixel_q[i][j -: 8]);
• end
• the LSB's are first assigned to a temp variablevthen the 8 bit temp is pushed into payload queue
• for(int j=31;j>0;j=j-10) begin
• temp = (temp<<2) | pixel_q[i][j -: 2];
• end
• payld_q.push_back(temp);
• end
SCOREBOARD
• Using macro `uvm_analysis_imp_decl(<_portname>), to declare
uvm_analysis_imp_<_portname> class.
• We need 2 import, one for expected packet which is sent by driver and received packet which is
coming from receiver.

Declare 2 imports using `uvm_analysis_imp_decl macros should not be defined inside the class.
• `uvm_analysis_imp_decl(_exp_data)
• `uvm_analysis_imp_decl(_obs_data)
• `uvm_analysis_imp_decl(_exp_data_apb)
• `uvm_analysis_imp_decl(_obs_data_cci)

• uvm_analysis_imp_exp_data #(csi2_llp_pkt_txd, csi2_scb ) ppi_pkt_export;


• uvm_analysis_imp_obs_data #(csi2_llp_pkt_txd, csi2_scb ) pixel_pkt_export;
• uvm_analysis_imp_exp_data_apb #(csi2_cci_pkt_txd, csi2_scb ) apb_pkt_export;
• uvm_analysis_imp_obs_data_cci #(csi2_cci_pkt_txd, csi2_scb ) cci_pkt_export;
Cnt…
The above macro, creates write_<_portname>(). This method
has to be define as per our requirements.
• virtual function write_exp_data(csi2_llp_pkt_txd exp_data);
• virtual function write_obs_data(csi2_llp_pkt_txd obs_data);
• virtual function write_exp_data_apb(csi2_cci_pkt_txd exp_data);
• virtual function write_obs_data_cci(csi2_cci_pkt_txd obs_data);

Declare a queue which stores the expected packets.


• csi2_llp_pkt_txd csi2_llp_pkt_q[$];
• csi2_cci_pkt_txd csi2_apb_pkt_q[$];

Das könnte Ihnen auch gefallen