Protocol description :-
•MCLK - Clock
•RESET - Reset
•PER_EN: when this signal is active, read access are executed during the current MCLK cycle while write access will be executed with the next MCLK rising edge. Note that this signal is HIGH ACTIVE.
• PER_ADDR: peripheral register address of the 16 bit word which is going to be accessed. It is to be noted that a 14 bit address will always be provided from the openMSP430 to the peripheral in order to accommodate the biggest possible PER_SIZE Verilog configuration option (i.e. 32kB as opposed to 512B by default). Note: in order to calculate the core logical address from the peripheral register physical address, the formula goes as following: LOGICAL@=2*PHYSICAL@
• PER_DOUT: the peripheral output word will be updated with every valid read/write access, it will be set to 0 otherwise.
• PER_WE: this signal selects which byte should be written during a valid access. PER_WE[0] will activate a write on the lower byte, PER_WE[1] a write on the upper byte. Note that these signals are HIGH ACTIVE.
• PER_DIN: the peripheral input word will be written with the valid write access according to the PER_WE value.
→ How to write the sampling logic to control the sequential write and combination read ?
I tried to write below code but i show that last transaction is not being sampled by the monitor and testcase completes without capturing that even i used the set_drain_time of uvm method to add some delay for completion but i feel there is some mistake in the monitor logic so i wanted to correct that.
- Driver CODE
task get_and_drive(uvm_phase phase);
bit pkt_drive_pending;
bit got_item_from_seqr;
uvm_info(get_name(),"get_and_drive started",UVM_HIGH); fork : MAIN_FORK begin : ASYNC_RESET_CHECK
uvm_info(get_name(),“waiting for async reset”,UVM_HIGH);
@(posedge p_vif.puc_reset);
drive_reset_signals();
if (pkt_drive_pending && got_item_from_seqr) begin
seq_item_port.item_done();
phase.drop_objection(this);
end
end : ASYNC_RESET_CHECK
begin : DRIVE_DET_THREAD
uvm_info(get_name(),"Waiting for sequence item",UVM_HIGH); seq_item_port.get_next_item(req); got_item_from_seqr = 1'b1;
uvm_info(get_name(),$psprintf("Drive got item from sequencer : %s ",req.sprint()),UVM_HIGH);
phase.raise_objection(this);
// flag to monitor packet driving in progress
pkt_drive_pending = 1’b1;
if(req.rw_nop == READ) begin
read_transfer(req);
end
else if (req.rw_nop == WRITE_LO || req.rw_nop == WRITE_HI || req.rw_nop == WRITE_WO) begin
write_transfer(req);
end
else if (req.rw_nop == NOP) begin
nop_transfer(req);
end
else
uvm_error (get_type_name(), $sformatf(" Transfer type not supported")) pkt_drive_pending = 1'b0; repeat(req.clk_dly) begin @(posedge p_vif.MCLK);
uvm_info(get_name(),“asserted delay cylce”,UVM_HIGH);
end
seq_item_port.item_done();
got_item_from_seqr = 1’b0;
phase.drop_objection(this);
end : DRIVE_DET_THREAD
join_any
disable fork;
wait(p_vif.puc_reset ==0);
//@(negedge p_vif.puc_reset && p_vif.MCLK);
`uvm_info(get_name(),“get_and_drive completed”,UVM_HIGH);
endtask : get_and_drive - Monitor code
virtual task main_phase(uvm_phase phase);
super.reset_phase(phase);
while(1) begin
uvm_info(get_type_name(), $psprintf("Monitor collect transfer"), UVM_NONE) collect_transaction(phase); end endtask task collect_transaction(uvm_phase phase); bit pkt_sample_pending; fork : MAIN_FORK begin
uvm_info(“MONITOR_WAIT_ASYNC_RESET”,“waiting for async reset”,UVM_HIGH);
@(posedge p_vif.puc_reset);
uvm_info("MONITOR_ASYNC_RESET_DETECTED","async reset detected",UVM_HIGH); if(pkt_sample_pending == 1'b1)begin phase.drop_objection(this); end
uvm_info(get_full_name(),“Detected Reset, stopping monitoring of data”,UVM_NONE)
end
begin
@(posedge p_vif.MCLK);
phase.raise_objection(this);
pkt_sample_pending =1’b1;
if (p_vif.per_en == 1’b1 && p_vif.per_wen != 2’b00) begin
rcv_pkt.per_addr = p_vif.per_addr;
rcv_pkt.per_din = p_vif.per_din;
if(p_vif.per_wen == 2’b01) begin
rcv_pkt.rw_nop = WRITE_LO;
end
else if (p_vif.per_wen == 2’b10) begin
rcv_pkt.rw_nop = WRITE_HI;
end
else if (p_vif.per_wen == 2’b11) begin
rcv_pkt.rw_nop = WRITE_WO;
end
uvm_info(get_type_name(), $psprintf("Monitor WRITE PKT \n%s", rcv_pkt.sprint()), UVM_HIGH) end else if (p_vif.per_en == 1'b1 && p_vif.per_wen == 2'b00) begin rcv_pkt.per_addr = p_vif.per_addr;
uvm_info(get_type_name(), $psprintf(“Monitor READ PKT \n%s”, rcv_pkt.sprint()), UVM_HIGH)
p_vif.per_dout <= rcv_pkt.per_dout;
rcv_pkt.rw_nop = READ;
end
else begin
if(nop_check_enable == 1’b0) begin
rcv_pkt.per_addr = p_vif.per_addr;
rcv_pkt.per_dout = p_vif.per_dout;
rcv_pkt.per_din = p_vif.per_din;
rcv_pkt.rw_nop = NOP;
end
end
`uvm_info(get_type_name(), $psprintf(“Monitor \n%s”, rcv_pkt.sprint()), UVM_NONE)
cov_collect_port.write(rcv_pkt);
pkt_sample_pending =1’b0;
phase.drop_objection(this);
end
join_any
disable fork;
wait(p_vif.puc_reset == 0);
endtask - simulation Result
UVM_INFO peripheral_driver.sv(49) @ 30: uvm_test_top.env.peripheral_agnt.driver [uvm_test_top.env.peripheral_agnt.driver] in main_phase
UVM_INFO peripheral_monitor.sv(64) @ 30: uvm_test_top.env.peripheral_agnt.monitor [peripheral_monitor] Monitor collect transfer
UVM_INFO peripheral_monitor.sv(129) @ 35: uvm_test_top.env.peripheral_agnt.monitor [peripheral_monitor] Monitor
Name Type Size Value
rcv_pkt peripheral_transfer - @651
rw_nop direction_enum 3 NOP
per_addr integral 15 'h0
per_din integral 16 'h0
per_dout integral 16 'h0
UVM_INFO peripheral_monitor.sv(64) @ 35: uvm_test_top.env.peripheral_agnt.monitor [peripheral_monitor] Monitor collect transfer
UVM_INFO peripheral_driver.sv(147) @ 35: uvm_test_top.env.peripheral_agnt.driver [peripheral_driver] Driving
Name Type Size Value
req peripheral_transfer - @676
rw_nop direction_enum 3 WRITE_WO
per_addr integral 15 'h3
per_din integral 16 'h35bd
per_dout integral 16 'h0
begin_time time 64 30
depth int 32 'd3
parent sequence (name) string 6 wr_seq
parent sequence (full name) string 53 uvm_test_top.env.peripheral_agnt.sequencer.seq.wr_seq
sequencer string 42 uvm_test_top.env.peripheral_agnt.sequencer
UVM_INFO peripheral_monitor.sv(129) @ 45: uvm_test_top.env.peripheral_agnt.monitor [peripheral_monitor] Monitor
Name Type Size Value
rcv_pkt peripheral_transfer - @651
rw_nop direction_enum 3 WRITE_WO
per_addr integral 15 'h3
per_din integral 16 'h35bd
per_dout integral 16 'h0
UVM_INFO peripheral_monitor.sv(64) @ 45: uvm_test_top.env.peripheral_agnt.monitor [peripheral_monitor] Monitor collect transfer
UVM_INFO peripheral_driver.sv(156) @ 45: uvm_test_top.env.peripheral_agnt.driver [peripheral_driver] Driving
Name Type Size Value
req peripheral_transfer - @701
rw_nop direction_enum 3 NOP
per_addr integral 15 'h3485
per_din integral 16 'h744d
per_dout integral 16 'h0
begin_time time 64 35
depth int 32 'd3
parent sequence (name) string 7 nop_seq
parent sequence (full name) string 54 uvm_test_top.env.peripheral_agnt.sequencer.seq.nop_seq
sequencer string 42 uvm_test_top.env.peripheral_agnt.sequencer
45mem write xxxx
UVM_INFO peripheral_monitor.sv(129) @ 55: uvm_test_top.env.peripheral_agnt.monitor [peripheral_monitor] Monitor
Name Type Size Value
rcv_pkt peripheral_transfer - @651
rw_nop direction_enum 3 NOP
per_addr integral 15 'h3485
per_din integral 16 'h744d
per_dout integral 16 'h0
UVM_INFO peripheral_monitor.sv(64) @ 55: uvm_test_top.env.peripheral_agnt.monitor [peripheral_monitor] Monitor collect transfer
UVM_INFO peripheral_driver.sv(125) @ 55: uvm_test_top.env.peripheral_agnt.driver [peripheral_driver] Driving
Name Type Size Value
req peripheral_transfer - @709
rw_nop direction_enum 3 READ
per_addr integral 15 'h3
per_din integral 16 'h2aa1
per_dout integral 16 'h0
begin_time time 64 45
depth int 32 'd3
parent sequence (name) string 6 rd_seq
parent sequence (full name) string 53 uvm_test_top.env.peripheral_agnt.sequencer.seq.rd_seq
sequencer string 42 uvm_test_top.env.peripheral_agnt.sequencer
55mem read 35bd
UVM_INFO /apps/vcsmx/vcs/P-2019.06-1//etc/uvm-1.1/src/base/uvm_objection.svh(1273) @ 155: reporter [TEST_DONE] ‘run’ phase is ready to proceed to the ‘extract’ phase
UVM_INFO per_base_test.sv(50) @ 155: uvm_test_top [per_wr_rd_test] ---------------------------------------
UVM_INFO per_base_test.sv(51) @ 155: uvm_test_top [per_wr_rd_test] ---- TEST PASS ----
UVM_INFO per_base_test.sv(52) @ 155: uvm_test_top [per_wr_rd_test] ---------------------------------------
MEMORY DUT code
// Write data to Memory
always @(posedge clk)
if (per_en)
if(per_wen) begin
mem[per_addr] <= per_din;
$display($time ,“mem write %0h”, mem[per_addr]);
end
// Read data from memory
always @(per_en or per_wen)
if (per_en)
if(!per_wen) begin
per_dout = mem[per_addr];
$display($time ,“mem read %0h”, per_dout);
end