| @@ -0,0 +1,211 @@ | |||
| class axi_driver extends uvm_driver#(axi_seq_item); | |||
| `uvm_component_utils(axi_driver) | |||
| virtual intf vif; | |||
| axi_seq_item tx; | |||
| int temp[]; | |||
| int burst_len; | |||
| int burst_size; | |||
| int total_tr; | |||
| int wrap_lower_boundary; | |||
| int wrap_upper_boundary; | |||
| function new(string name="axi_driver",uvm_component_parent); | |||
| super.new(name,parent); | |||
| endfunction | |||
| function void build_phase(uvm_phase phase); | |||
| super.new(); | |||
| tx=axi_seq_item::type_id::create("tx",this); | |||
| if(!uvm_config_db#(virtual intf)::get("this",*,"intf",vif) | |||
| `uvm_error(get_type_name(),$sformatf("failed for get vif")) | |||
| endfunction | |||
| task run_phase(uvm_phase phase) | |||
| forever begin | |||
| seq_item_port.get_next_item(tx); | |||
| drive(); | |||
| seq_item_port.item_done(tx); | |||
| end | |||
| endtask | |||
| task drive(); | |||
| if(tx.wr_rd) | |||
| begin | |||
| write_address(); | |||
| write_data(); | |||
| write_response(); | |||
| end | |||
| else | |||
| read_address(); | |||
| endtask | |||
| ////////write address/////// | |||
| task write_adress(); | |||
| @(posedge vif.clk) | |||
| tx.awvalid<=1; | |||
| vif.awvalid<=tx.awvalid; | |||
| vif.awid<=tx.awid; | |||
| //vif.awaddr<=tx.awaddr; | |||
| vif.awsize<=tx.awsize; | |||
| vif.awlen<=tx.awlen; | |||
| vif.awburst<=tx.awburst; | |||
| //////////fixed burst//////////// | |||
| if(tx.awburst==2'b00) | |||
| vif.awaddr<=tx.awaddr; | |||
| ////////increament burst//////// | |||
| else if(awburst==2'b01)begin | |||
| vif.awaddr<=tx.awaddr; | |||
| for(i=0;i<awlen;i++) | |||
| vif.awaddr<=(tx.awaddr+(2**awsize)); | |||
| end | |||
| ////////wrap burst///////// | |||
| else if(tx.awburst=2'b10)begin | |||
| begin | |||
| if(((tx.awaddr)%2**awsize)==0)begin | |||
| burst_len=tx.awlen+1; | |||
| burst_size=2**(tx.awsize); | |||
| total_tr=burst_len*burst_size; | |||
| wrap_lower_boundary=int'((tx.awaddr)/(total_tr))*total_tr; | |||
| wrap_upper_boundary=wrap_lower_boundary+total_tr; | |||
| end | |||
| vif.awlock<=tx.awlock; | |||
| @(posedge vif.clk) | |||
| wait(vif.awready) | |||
| @(posedge vif.clk) | |||
| tx.awvalid<=0; | |||
| vif.awvalid<=tx.awvalid; | |||
| endtask | |||
| //////write data/////////// | |||
| task write_data(); | |||
| @posedge vif.clk) | |||
| tx.wvalid<=1; | |||
| vif.wvalid<=tx.wvalid; | |||
| vif.wid<=tx.wid; | |||
| foreach(tx.wdata[i,j]) | |||
| begin | |||
| temp[i][8*i+:8]<=tx.wdata[i][j]; | |||
| end | |||
| for(i=0;i<awlen+1;i++); | |||
| begin | |||
| vif.wdata<=temp[i]; | |||
| tx.wvalid<=1; | |||
| vif.wvalid<=tx.wvalid; | |||
| vif.wlast<=awlen==i?1:0; | |||
| end | |||
| wait(vif.wready); | |||
| //endtask | |||
| @posedge vif.clk) | |||
| tx.wvalid<=0; | |||
| vif.wvalid<=tx.wvalid; | |||
| endtask | |||
| //////////write response ////////// | |||
| task write_response(); | |||
| @posedge vif.clk) | |||
| vif.bid<=tx.bid; | |||
| vif.bresp<=tx.bresp; | |||
| tx.bvalid<=1; | |||
| vif.bvalid<=tx.bvalid; | |||
| @posedge vif.clk) | |||
| wait(vif.bready); | |||
| @posedge vif.clk) | |||
| tx.bvalid<=0; | |||
| vif.bvalid<=tx.bvalid; | |||
| endtask | |||
| /////////read address///////// | |||
| task read_adress(); | |||
| @(posedge vif.clk) | |||
| tx.arvalid<=1; | |||
| vif.arvalid<=tx.arvalid; | |||
| vif.arid<=tx.arid; | |||
| //vif.araddr<=tx.araddr; | |||
| vif.arsize<=tx.arsize; | |||
| vif.arlen<=tx.arlen; | |||
| vif.arburst<=tx.arburst; | |||
| //////////fixed burst//////////// | |||
| if(tx.arburst==2'b00) | |||
| vif.araddr<=tx.araddr; | |||
| vif.arid<=tx.arid; | |||
| ////////increament burst//////// | |||
| else if(arburst==2'b01)begin | |||
| vif.araddr<=tx.araddr; | |||
| for(i=0;i<arlen;i++) | |||
| begin | |||
| vif.arid<=tx.arid; | |||
| vif.araddr<=(tx.araddr+(2**arsize)); | |||
| end | |||
| ////////wrap burst///////// | |||
| else if(tx.arburst=2'b10)begin | |||
| begin | |||
| if(((tx.araddr)%2**arsize)==0)begin | |||
| vif.arid<=tx.arid; | |||
| burst_len=tx.arlen+1; | |||
| burst_size=2**(tx.arsize); | |||
| total_tr=burst_len*burst_size; | |||
| wrap_lower_boundary=int'((tx.araddr)/(total_tr))*total_tr; | |||
| wrap_upper_boundary=wrap_lower_boundary+total_tr; | |||
| end | |||
| vif.arlock<=tx.arlock; | |||
| @(posedge vif.clk) | |||
| wait(vif.arready) | |||
| @(posedge vif.clk) | |||
| tx.arvalid<=0; | |||
| vif.arvalid<=tx.arvalid; | |||
| endtask | |||
| endclass | |||
| @@ -0,0 +1,85 @@ | |||
| // axi write sequence | |||
| class axi_write_sequence extends uvm_sequence#(axi_seq_item); | |||
| `uvm_object_utils(axi_write_sequence); | |||
| function new(string name="axi_write_sequence"); | |||
| super.new(name); | |||
| endfunction | |||
| task body(); | |||
| req=axi_seq_item::type_id::create(req); | |||
| start_item(req); | |||
| assert(req.randomize()with{req.wr_rd==1;req.awaddr==0x08;req.awburst==2'b 10;req.awlen==3;req.awsize==2;req.wdata==0x22fb;}); | |||
| finish_item(req); | |||
| endtask | |||
| endclass | |||
| // axi_read_sequence | |||
| class axi_read_sequence extends uvm_sequence#(axi_seq_item); | |||
| `uvm_object_utils(axi_read_sequence); | |||
| function new(string name="axi_read_sequence"); | |||
| super.new(name); | |||
| endfunction | |||
| task body(); | |||
| req=axi_seq_item::type_id::create(req); | |||
| start_item(req); | |||
| assert(req.randomize()with{req.wr_rd==0;req.araddr==0x08;arlen==3;arburst==2'b 10;}); | |||
| finish_item(req); | |||
| endtask | |||
| endclass | |||
| // axi aligned sequence | |||
| class axi_aligned_sequence extends uvm_sequence#(axi_seq_item); | |||
| `uvm_object_utils(axi_aligned_sequence); | |||
| function new(string name="axi_aligned_sequence"); | |||
| super.new(name); | |||
| endfunction | |||
| task body(); | |||
| req=axi_seq_item::type_id::create(req); | |||
| start_item(req); | |||
| assert(req.randomize()with{req.wr_rd==1;req.awaddr==0x08;req.awsize==3;req.awburst==2'b 10;req.wdata==0xfa30;}); | |||
| finish_item(req); | |||
| endtask | |||
| endclass | |||
| // write followed by read | |||
| class write_read_sequence extends uvm_sequence#(axi_seq_item); | |||
| `uvm_object_utils(write_read_sequence); | |||
| axi_write_sequence axi_wr_seq; | |||
| axi_read_sequence axi_rd_seq; | |||
| function new(string name="write_read_sequence"); | |||
| super.new(name); | |||
| endfunction | |||
| task body(); | |||
| `uvm_do(axi_wr_seq); | |||
| `uvm_do(axi_rd_seq); | |||
| end | |||
| endclass | |||
| @@ -0,0 +1,125 @@ | |||
| `include "uvm_macros.svh" | |||
| import uvm_pkg::*; | |||
| class axi_seq_item extends uvm_seq_item; | |||
| //'uvm_object_utils(axi_seq_item); | |||
| function new(string name="axi_seq_item") | |||
| super.new(name); | |||
| endfunction | |||
| //write adress channel signals | |||
| rand bit wr_rd; | |||
| rand bit [3:0] awid; | |||
| rand logic[31:0] awaddr; | |||
| rand logic[2:0] awsize; | |||
| rand logic[3:0] awlen; | |||
| rand logic[1:0] awburst; | |||
| rand logic[1:0] awlock; | |||
| logic awvalid; | |||
| logic awready; | |||
| //write data channel | |||
| rand bit [3:0] wid; | |||
| rand logic[31:0] wdata[][]; | |||
| logic[3:0] wstrb; | |||
| logic wlast; | |||
| logic wvalid; | |||
| logic wready; | |||
| // write response channel | |||
| rand bit []3:0]bid; | |||
| logic[1:0] bresp; | |||
| logic bvalid; | |||
| logic bready; | |||
| // read adress channel | |||
| rand bit [3:0] arid; | |||
| rand logic[31:0] araddr; | |||
| rand logic[2:0] arsize; | |||
| rand logic[3:0] arlen; | |||
| rand logic[1:0] arburst; | |||
| rand logic[1:0] arlock; | |||
| logic arvalid; | |||
| logic arready; | |||
| // read data channel | |||
| rand bit [3:0] rid; | |||
| logic[31:0] rdata; | |||
| logic[3:0]rresp; | |||
| logic rlast; | |||
| logic rvalid; | |||
| logic rready; | |||
| `uvm_object_utils_begin(axi_seq_item) | |||
| `uvm_field_int(awid,UVM_ALL_ON) | |||
| `uvm_field_int(awaddr,UVM_ALL_ON) | |||
| `uvm_field_int(awsize,UVM_ALL_ON) | |||
| `uvm_field_int(awlen,UVM_ALL_ON) | |||
| `uvm_field_int(awburst,UVM_ALL_ON) | |||
| `uvm_field_int(awlock,UVM_ALL_ON) | |||
| `uvm_field_int(awvalid,UVM_ALL_ON) | |||
| `uvm_field_int(awready,UVM_ALL_ON) | |||
| `uvm_field_int(wid,UVM_ALL_ON) | |||
| `uvm_field_int(wdata,UVM_ALL_ON) | |||
| `uvm_field_int(wlast,UVM_ALL_ON) | |||
| `uvm_field_int(wstrb,UVM_ALL_ON) | |||
| `uvm_field_int(wvalid,UVM_ALL_ON) | |||
| `uvm_field_int(wready,UVM_ALL_ON) | |||
| `uvm_field_int(bid,UVM_ALL_ON) | |||
| `uvm_field_int(bresp,UVM_ALL_ON) | |||
| `uvm_field_int(bvalid,UVM_ALL_ON) | |||
| `uvm_field_int(bready,UVM_ALL_ON) | |||
| `uvm_field_int(arid,UVM_ALL_ON) | |||
| `uvm_field_int(araddr,UVM_ALL_ON) | |||
| `uvm_field_int(arsize,UVM_ALL_ON) | |||
| `uvm_field_int(arlen,UVM_ALL_ON) | |||
| `uvm_field_int(arsize,UVM_ALL_ON) | |||
| `uvm_field_int(arburst,UVM_ALL_ON) | |||
| `uvm_field_int(arlock,UVM_ALL_ON) | |||
| `uvm_field_int(arvalid,UVM_ALL_ON) | |||
| `uvm_field_int(arready,UVM_ALL_ON) | |||
| `uvm_field_int(rid,UVM_ALL_ON) | |||
| `uvm_field_int(rdata,UVM_ALL_ON) | |||
| `uvm_field_int(rlast,UVM_ALL_ON) | |||
| `uvm_field_int(rresp,UVM_ALL_ON) | |||
| `uvm_field_int(rvalid,UVM_ALL_ON) | |||
| `uvm_field_int(rready,UVM_ALL_ON) | |||
| `uvm_object_utils_end | |||
| //constraints for axi | |||
| constraint aligned_addr{awadd%2**awsize==0;} | |||
| constraint wrap_addr{solve awburst before awlen | |||
| if(awburst==2'b 10) | |||
| awlen inside{1,3,7,15};} | |||
| constraint wid_sig{awid==wid;} | |||
| constraint rid_sig{arid==rid;} | |||
| constraint axi_4kb{awaddr%4096+(2**awsize*(awlen+1))<=4096;} | |||
| //:constrain | |||
| endclass:axi_seq_item | |||