Chapter 5 – Driver

来源:互联网 发布:游戏端口被屏蔽怎么办 编辑:程序博客网 时间:2024/05/03 16:28

The driver is a block whose role is tointeract with the DUT. The driver pulls transactions from the sequencer and

sends them repetitively to the signal-levelinterface. This interaction will be observed and evaluated by another block,

the monitor, and as a result, the driver’sfunctionality should only be limited to send the necessary data to the DUT.

In order to interact with our adder, thedriver will execute the following operations: control the en_i signal, send the

transactions pulled from the sequencer tothe DUT inputs and wait for the adder to finish the operation.

So, we are going to follow these steps:

1. Derive the driver class from theuvm_driver base class

2. Connect the driver to the signalinterface

3. Get the item data from the sequencer,drive it to the interface and wait for the DUT execution

4. Add UVM macros

In Code 5.1 you can find the base code patternwhich is going to be used in our driver.

class simpleadder_driver extendsuvm_driver#(simpleadder_transaction);

`uvm_component_utils(simpleadder_driver)

//Interface declaration

protected virtual simpleadder_if vif;

function new(string name, uvm_componentparent);

super.new(name, parent);

endfunction: new

function void build_phase(uvm_phase phase);

super.build_phase(phase);

void'(uvm_resource_db#(virtualsimpleadder_if)::read_by_name(.scope("ifs")

, .name("simpleadder_if"),.val(vif)));

endfunction: build_phase

task run_phase(uvm_phase phase);

//Our code here

endtask: run_phase

endclass: simpleadder_driver

Code 5.1 – Driver component –simpleadder_driver.sv

The code might look complex already but whatit’s represented it’s the usual code patterns from UVM. We are going

to focus mainly on the run_phase() taskwhich is where the behaviour of the driver will be stated. But before that, a

simple explanation of the existing lineswill be given:

 Line 1 derives a class namedsimpleadder_driver from the UVM class uvm_driver.

The #(simpleadder_transaction) is aSystemVerilog parameter and it represents the data type that it will be

retrieved from the sequencer.

 Line 2 refers to the UVM utilities macroexplained on chapter 2.

 Lines 7 to 9 are the class constructor.

 Line 11 starts the build phase of theclass, this phase is executed before the run phase.

 Line 13 gets the interface from thefactory database. This is the same interface we instantiated earlier in the

top block.

 Line 16 is the run phase, where the codeof the driver will be executed.

Now that the driver class was explained,you might be wondering: “What exactly should I write in the run phase?”

Consulting the state machine from thechapter 1, we can see that the DUT waits for the signalen_i to be triggered

before listening to the ina and inb inputs,so we need to emulate the states 0 and 1. Although we don’t intend to

sample the output of the DUT with thedriver, we still need to respect it, which means, before we send another

sequence, we need to wait for the DUT tooutput the result.

To sum up, in the run phase the followingactions must be taken into account:

1. Get a sequence item

2. Control the en_i signal

3. Drive the sequence item to the bus

4. Wait a few cycles for a possible DUTresponse and tell the sequencer to send the next sequence item

The driver will end its operation themoment the sequencer stops sending transactions. This is done automatically by

the UVM API, so the designer doesn’t needto to worry with this kind of details.

In order to write the driver, it’s easierto implement the code directly as a normal testbench and observe its behaviour

through waveforms. As a result, in the nextsubchapter (chapter 5.1), the driver will first be implemented as a normal

testbench and then we will reuse the codeto implement the run phase (chapter 5.2).

Chapter 5.1 – Creating the driver as anormal testbench

For our normal testbench we will useregular Verilog code. We will need two things: generate the clock and

idesginate an end for the simulation. Asimulation of 30 clock cycles was defined for this testbench.

The code is represented in Code 5.2.

//Generates clock

initial begin

#20;

forever #20 clk = ! clk;

end

//Stops testbench after 30 clock cyles

always@(posedge clk)

begin

counter_finish = counter_finish + 1;

if(counter_finish == 30) $finish;

end

Code 5.2 – Clock generation for the normaltestbench

The behaviour of the driver follows in Code5.3.

//Driver

always@(posedge clk)

begin

//State 0: Drives the signal en_o

if(counter_drv==0)

begin

en_i = 1'b1;

state_drv = 1;

end

if(counter_drv==1)

begin

en_i = 1'b0;

end

case(state_drv)

//State 1: Transmits the two inputs ina andinb

1: begin

ina = tx_ina[1];

inb = tx_inb[1];

tx_ina = tx_ina << 1;

tx_inb = tx_inb << 1;

counter_drv = counter_drv + 1;

if(counter_drv==2) state_drv = 2;

end

//State 2: Waits for the DUT to respond

2: begin

ina = 1'b0;

inb = 1'b0;

counter_drv = counter_drv + 1;

//After the supposed response, the TBstarts over

if(counter_drv==6)

begin

counter_drv = 0;

state_drv = 0;

//Restores the values of ina and inb

//to send again to the DUT

tx_ina <= 2'b11;

tx_inb = 2'b10;

end

end

endcase

end

Code 5.3 – Part of the driver

For this testbench, we are sending thevalues of tx_ina and tx_inb to the DUT, they are defined in the beginning of

the testbench (you can see the completecode attached to this guide).

We are sending the same value multipletimes to see how the driver behaves by sending consecutive transactions.

After the execution of the Makefile, a filenamed simpleadder.dump will be created by VCS. To see the waveforms of

the simulation, we just need to open itwith DVE.

The waveform for the driver is representedon Figure 5.1


Figure 5.1 – Driver

waveform

It’s possible to see that the driver isworking as expected: it drives the signal en_i on and off as well the DUT

inputs ina and inb and it waits for aresponse of the DUT before sending the transaction again.

Chapter 5.2 – Implementing the UVM driver

After we have verified that our driverbehaves as expected, we are ready to move the code into the run phase as

seen in Code 5.4.

virtual task drive();

simpleadder_transaction sa_tx;

integer counter = 0, state = 0;

vif.sig_ina = 0'b0;

vif.sig_inb = 0'b0;

vif.sig_en_i = 1'b0;

forever begin

if(counter==0) begin

//Gets a transaction from the sequencer and

//stores it in the variable 'sa_tx'

seq_item_port.get_next_item(sa_tx);

end

@(posedge vif.sig_clock)

begin

if(counter==0) begin

vif.sig_en_i = 1'b1;

state = 1;

end

if(counter==1) begin

vif.sig_en_i = 1'b0;

end

case(state)

1: begin

vif.sig_ina = sa_tx.ina[1];

vif.sig_inb = sa_tx.inb[1];

sa_tx.ina = sa_tx.ina &lt;&lt; 1;

sa_tx.inb = sa_tx.inb &lt;&lt; 1;

counter = counter + 1;

if(counter==2) state = 2;

end

2: begin

vif.sig_ina = 1'b0;

vif.sig_inb = 1'b0;

counter = counter + 1;

if(counter==6) begin

counter = 0;

state = 0;

//Informs the sequencer that the

//current operation with

//the transaction was finished

seq_item_port.item_done();

end

end

endcase

end

end

endtask: drive

Code 5.4 - Task for the run_phase()

The ports of the DUT are acessed throughthe virtual interface with vif.<signal> as can be seen in lines 4 to 6.

Lines 12 and 50 use a special variable fromUVM, the seq_item_port to communicate with the sequencer. The driver

calls the method get_next_item() to get anew transaction and once the operation is finished with the current

transaction, it calls the methoditem_done(). If the driver calls get_next_item() but the sequencer doesn’t haveany

transactions left to transmit, the currenttask returns.

This variable is actually a UVM port and itconnects to the export from the sequencer namedseq_item_export. The

connection is made by an upper class, inour case, the agent. Ports and exports are going to be further explai ned

in chapter 6.0.1.

This concludes our driver, the full codefor the driver can be found in the filesimpleadder_driver.sv. In Figure 5.2,the

state of the verification environment withthe driver can be seen.


Figure 5.2State of the verification environment with the driver





0 0
原创粉丝点击