Hongnhattl Posted July 16, 2015 Report Posted July 16, 2015 Hi all, I have a SPI interface, it has three modes to transfer the data out on IO[0:7]. In SPI standard there is just IO[0] is used. QPI mode, it uses IO[3:0] and In OPI mode, the whole IO are used. When driver receives a req from sequencer, it drives that req to the interface depending on modes. The interface sometimes goes with SPI, sometimes QPI or OPI. And I want to monitor the tx data, but I dont't know how to setup the monitor to sample the data corresponding to the mode that the driver has used. Are there ways to make monitor works in the same mode with the driver? Thank you! Quote
ruchir.bharti Posted July 16, 2015 Report Posted July 16, 2015 Hello, In general in any uvm_agent, driver and monitor are bind with interface, an interface which declares signal, clocking block, function, task many more.. for SPI bus, data transfer can be done in any mode as you said SPI,DPI(Dual), QPI, OPI(Octa) also there is flexibility of cmd-addr-data can be send different fashion as per memory device support. for verification purpose what i can recommend you is : when spi controller running in SPI mode which mean only 2 pins are supposed to toggle(im ignoring cs and clk for this discussion), then driver can drive other 6 pins to 'High-Z' so that monitor can identify running mode. generally signal defined in interface are of type "LOGIC", it have 4 values(0,1,X,Z) in which monitor logic can work on signal value. Similarlly for QPI, drive remaining 4 pins to 'High-Z'. I hope that help!! With Best Regards Ruchir Quote
tudor.timi Posted July 16, 2015 Report Posted July 16, 2015 I'd rather suggest to have a configuration field that states in which mode you are (single, dual, quad, octa). This field could be part of a configuration object that is shared by both objects: typedef enum { SINGLE, DUAL, QUAD, OCTA } mode_t; class spi_config extends uvm_object; rand mode_t mode; // ... endclass class spi_driver extends uvm_driver #(...); spi_config cfg; // ... endclass class spi_monitor extends uvm_monitor #(...); spi_config cfg; // ... endclass class spi_agent extends uvm_agent; spi_config cfg; spi_driver driver; spi_monior monitor; virtual function void build_phase(...); // ... // create and randomize config // ... driver.cfg = cfg; monitor.cfg = cfg; endfunction Hongnhattl 1 Quote
tudor.timi Posted July 16, 2015 Report Posted July 16, 2015 for verification purpose what i can recommend you is : when spi controller running in SPI mode which mean only 2 pins are supposed to toggle(im ignoring cs and clk for this discussion), then driver can drive other 6 pins to 'High-Z' so that monitor can identify running mode. generally signal defined in interface are of type "LOGIC", it have 4 values(0,1,X,Z) in which monitor logic can work on signal value. Similarlly for QPI, drive remaining 4 pins to 'High-Z'. What if you have to verify an SPI master using the same UVC? In that case you can't rely that the design is driving Z when in a certain mode. This is exactly what you need to verify. I'd avoid making such assumptions. Quote
ruchir.bharti Posted July 16, 2015 Report Posted July 16, 2015 What if you have to verify an SPI master using the same UVC? In that case you can't rely that the design is driving Z when in a certain mode. This is exactly what you need to verify. I'd avoid making such assumptions. Hello Tudor, Thanks for sharing your thought, But what i understood from initial question is development of monitor when UVC as master. ( i might be wrong) still if UVC as Master( which i assume SPI Controller) then it can control the respective signal and give flexibility to implementer to drive 'Z' on ports and monitor can capture 'Z', but if UVC as slave( Which i assume SPI Memory device) then i think it have to sample all/selected signal as per memory device behavior. Which means read and decode commands/Addrress/data of SPI protocol and sample/drive line accordingly. Since SLAVE dont know what kind of command will controller initiate. Regards Ruchir Quote
Hongnhattl Posted July 17, 2015 Author Report Posted July 17, 2015 Thanks for your replies, I helped me. By the way, let me ask one more question. The clock in my testbench can run with different frequency, in my spi_top_tb I instantiate a DUT hook up to the interface and then define the clock generation like the below module spi_top_tb; parameter cycle_1 = 3.5; SPI dut(svif); //Clock generation always #cycle_1 svif.SCK_PAD = ~svif.SCK_PAD; ... How can I edit it to make clock cycle become configurable? Thank you and Best regards, Nhat Quote
matteodc Posted July 22, 2015 Report Posted July 22, 2015 I would prefer an object oriented approach, i.e. a base class to implement common functionality and derived classes for specialization. Then, depending on the uvm_test randomization, type substitution by using the UVM factory. This approach reduces the code changes required in some scenarios. Regards Quote
ruchir.bharti Posted July 23, 2015 Report Posted July 23, 2015 Hello Nhat, An Ideal testbench should be fully controllable, modular and interoperable, which includes test should control generation of kind of stimulus, clock frequency, reset control, test signal. So to attain this i would recommend to have agent for each kind of signal ie 1) bus agents( data exchange bus like AXI, AMBA): normally drives/monitor bus signal and controlled by sequence. 2) Clock Agent : which generates all system clocks and clock frequency can be controlled by test/virtual sequence. here agent config is useful to control agent/clock for example : // Virtual Interface virtual clock_interface CLOCK; //------------------------------------------ // Data Members //------------------------------------------ // Is the agent active or passive uvm_active_passive_enum active = UVM_ACTIVE; // default clock Period in Mhz int unsigned clock_period = 30; // default duty cycle in terms of %age int unsigned duty_cycle = 50; // default start latencies in NS int unsigned start_latency = 100; // default clock state bit default_state = 0; // default jitter percentage int unsigned jitter = 0; // is clock stall during reset bit is_clk_stall_at_reset = 0; // ID flag int id=0; so when multiple clock_agent[x] is instantiated in uvm_env then id is used to configure agent as clock_agent[x].clock_period = XXX Mhz. so if uvm_env didnt program clock_period then default value will be consider. Also test/virtual sequence can override clock_period value as per requirement. 3) reset agent : similarly reset agent will control reset generation as a default value from agent config or controlled/overridden value from test/virtual sequence. I think this approach might you!! Regards Ruchir Quote
c4brian Posted July 23, 2015 Report Posted July 23, 2015 I think using the configuration object to share a variable, or using the factory are both good solutions. I definitely also recommend against using the state of bus signals to figure out the type of protocol it should expecting; it should already know this information. I've implemented an agent for DUT reset(s). If your clock generation does not change from test to test, I think an agent is not required; simply have an (optional) driver in the environment that drives the virtual interface; you can extend the driver to change clock characteristics. Quote
ruchir.bharti Posted July 24, 2015 Report Posted July 24, 2015 well brian, i agree with you if clock doesn't change much from test to test then there is no such requirement agent. Here drawback is on any change in testbench user need to recompile for every test. But the idea of having clock agent is to have complete solution for control-ability and observability. Also its a one time effort to create agent and this agent can be plug-in to any UVM verification environment. secondly having a monitor in clock_agent will helps in getting clock frequency which further can be used for coverage sample( basically help in capturing functional coverage where verification objective is to check whether verification have test the design with different clock ranges). in the end its a trade off between QUALITY vs COST vs TIME. user need to balance as verification is never ending process. c4brian 1 Quote
Hongnhattl Posted July 25, 2015 Author Report Posted July 25, 2015 Thanks all, alot of useful information! Ruchir, the approach about making agents brings me new idea that haven't thought about it, it's helpful information to me. About the reset agent, Do we need to write a scoreboard to check all the signal states whether or not it is reseted? Are there other approaches to check the reset status of the DUT? In my DUT to reset it, I need to send out an opcode instead of controling a reset signal. I made a agent called spi_master to handle sending out all of opcodes, if I make a new reset agent, it seems that I need to reuse the driver from the spi_master agent, i feel something exessive! Could you give me some advice? For enable signal agnets, do we need to write a seperate scoreboard to check for each case? Thanks Nhat Quote
Hongnhattl Posted July 26, 2015 Author Report Posted July 26, 2015 I'd rather suggest to have a configuration field that states in which mode you are (single, dual, quad, octa). This field could be part of a configuration object that is shared by both objects: typedef enum { SINGLE, DUAL, QUAD, OCTA } mode_t; class spi_config extends uvm_object; rand mode_t mode; // ... endclass class spi_driver extends uvm_driver #(...); spi_config cfg; // ... endclass class spi_monitor extends uvm_monitor #(...); spi_config cfg; // ... endclass class spi_agent extends uvm_agent; spi_config cfg; spi_driver driver; spi_monior monitor; virtual function void build_phase(...); // ... // create and randomize config // ... driver.cfg = cfg; monitor.cfg = cfg; endfunction Hi Tudor, I have a idea like this, I want to put the mode_t as rand transferred item for sequence, when driver gets this, it will configure for all other components like monitors and slave driver into the same mode as it. Is this possible? If not so, could you give me the relevant way to do that? Thanks Nhat Quote
tudor.timi Posted July 26, 2015 Report Posted July 26, 2015 I'm guessing your device can only be in one mode at a time and this is configured via some fields in some configuration registers. It doesn't make sense to start sending OCTA frames when the device is configured for DUAL mode operation, hence there's no point in having mode a field in your sequence/item. When you configure your device for a certain mode (via some register/bus sequence) you need to reach into the configuration for your SPI agent and update that with the appropriate value (e.g. write registers to configure the device for QUAD, set the config field in the SPI agent to QUAD as well). Hongnhattl 1 Quote
Hongnhattl Posted July 26, 2015 Author Report Posted July 26, 2015 I'm guessing your device can only be in one mode at a time and this is configured via some fields in some configuration registers. It doesn't make sense to start sending OCTA frames when the device is configured for DUAL mode operation, hence there's no point in having mode a field in your sequence/item. When you configure your device for a certain mode (via some register/bus sequence) you need to reach into the configuration for your SPI agent and update that with the appropriate value (e.g. write registers to configure the device for QUAD, set the config field in the SPI agent to QUAD as well).Hi Tudor,Your guessing is correct, by default the device work with SPI. To switch modes, spi master needs to send out the opcode to update the registers to configure the device into a certain mode. It turns out that if I want to test the device in OCTA mode, my first seq is to configure the device with OCTA mode by default standard, after that the device turns to work with the updated mode. The problem is that how can we let the SPI agent switch its mode during run time simulation? Can you give me some advice? Thanks Nhat Quote
tudor.timi Posted July 27, 2015 Report Posted July 27, 2015 When you start your config sequence, that's when you can also update you agent's config. Quote
Hongnhattl Posted July 30, 2015 Author Report Posted July 30, 2015 When you start your config sequence, that's when you can also update you agent's config. Hi Tudor Thanks for your reply The below is my code. I think with this code I can only configure mode before the run phase and I don't know how to change the spi_config when the simulation gets into the run phase. How should I change? virtual class spi_base_sequence extends uvm_sequence #(spi_transaction); `uvm_declare_p_sequencer(spi_sequencer) function new(string name="spi_base_seq"); super.new(name); endfunction virtual task pre_body(); if (starting_phase!=null) begin `uvm_info(get_type_name(), $sformatf("%s pre_body() raising %s objection", get_sequence_path(), starting_phase.get_name()), UVM_MEDIUM); starting_phase.raise_objection(this); end endtask virtual task post_body(); if (starting_phase!=null) begin `uvm_info(get_type_name(), $sformatf("%s post_body() dropping %s objection", get_sequence_path(), starting_phase.get_name()), UVM_MEDIUM); starting_phase.drop_objection(this); end endtask endclass : spi_base_sequence class spi_seq_req extends spi_base_sequence ; function new(string name = "spi_seq_req"); super.new(name); endfunction : new spi_transaction req; `uvm_object_utils(spi_seq_req) virtual task body(); `uvm_do_with(req, {opcode==8'h03;}) // This seq is transferred by SPI standard `uvm_do_with(req, {opcode==8'h06;}) // Write Enable opcode, transferred by SPI `uvm_do_with(req, {opcode==8'hE8;}) // Select OPI MODE, transferred by SPI `uvm_do_with(req, {opcode==8'h04;}) // After E8 opcode, the subsequence sequences will work with OPI `uvm_do_with(req, {opcode==8'h02;}) // Page Program, transferred by OPI endtask : body endclass: spi_seq_req In spi_test.sv: spi_config cfg =new ; function void build_phase(uvm_phase phase); //Set configure mode for Driver and Monitor mode_t = STR; std_t =SPI; cfg.std_t = std_t; cfg.mode = mode_t; spi_env = spi_env::type_id::create(.name("spi_env"), .parent(this)); uvm_config_db#(uvm_object_wrapper)::set(this,"*.spi_seqr.main_phase", "default_sequence",spi_seq_req::type_id::get()); Quote
Hongnhattl Posted July 30, 2015 Author Report Posted July 30, 2015 well brian, i agree with you if clock doesn't change much from test to test then there is no such requirement agent. Here drawback is on any change in testbench user need to recompile for every test. But the idea of having clock agent is to have complete solution for control-ability and observability. Also its a one time effort to create agent and this agent can be plug-in to any UVM verification environment. secondly having a monitor in clock_agent will helps in getting clock frequency which further can be used for coverage sample( basically help in capturing functional coverage where verification objective is to check whether verification have test the design with different clock ranges). in the end its a trade off between QUALITY vs COST vs TIME. user need to balance as verification is never ending process. Thanks all, alot of useful information! Ruchir, the approach about making agents brings me new idea that haven't thought about it, it's helpful information to me. About the reset agent, Do we need to write a scoreboard to check all the signal states whether or not it is reseted? Are there other approaches to check the reset status of the DUT? In my DUT to reset it, I need to send out an opcode instead of controling a reset signal. I made a agent called spi_master to handle sending out all of opcodes, if I make a new reset agent, it seems that I need to reuse the driver from the spi_master agent, i feel something exessive! Could you give me some advice? For enable signal agnets, do we need to write a seperate scoreboard to check for each case? Thanks Nhat Quote
c4brian Posted July 30, 2015 Report Posted July 30, 2015 The below is my code. I think with this code I can only configure mode before the run phase and I don't know how to change the spi_config when the simulation gets into the run phase. How should I change? You can change the configuration during the run phase; in your sequence, at the exact moment you want to change the mode of your agent monitor, just grab the configuration object for your agent and update the mode directly. Use the sequencer to get access to the agent config object. I like using the database: if( !uvm_config_db #( spi_config )::get( m_sequencer, "", "AGENT_CONFIG", cfg )) `uvm_fatal(report_id, "cannot find spi config resource" ) Quote
ruchir.bharti Posted July 31, 2015 Report Posted July 31, 2015 Thanks all, alot of useful information! Ruchir, the approach about making agents brings me new idea that haven't thought about it, it's helpful information to me. About the reset agent, Do we need to write a scoreboard to check all the signal states whether or not it is reseted? Are there other approaches to check the reset status of the DUT? In my DUT to reset it, I need to send out an opcode instead of controling a reset signal. I made a agent called spi_master to handle sending out all of opcodes, if I make a new reset agent, it seems that I need to reuse the driver from the spi_master agent, i feel something exessive! Could you give me some advice? For enable signal agnets, do we need to write a seperate scoreboard to check for each case? Thanks Nhat Reset @ DUT : during hard reset DUT or any digital design will restore to its initial predefined condition. which means all internal register, fifo, state machines are reset to its predefine or known state, or in short to its reset state. In addition to this, all output port are also reset`d, which means verification engg also need to check the reset value of output port using assertions( which i normally do or suggest ) apart from register values. Reset model : to apply reset you can create a interface which contain all reset signals (as some design have more than 1 reset signal+ test reset signals). This reset interface handle passed to your uvm_env by config_db. And finally in your uvm_env you can create task api which controls the reset with predefined intial state. Now test can call this reset API to drive reset condition as per requirement with time as parameter. CAUTION : If you want to apply reset multiple times during same simulation cycle, then you must take care of sequence should not block any sequencer. And reset information should be pass to all agent. so to answer your query regarding new reset agent, i would suggest a task would gives more flexibility and assertions will help in checking default state of DUT signals(so no need to create separate scoreboard). Im also assuming in your case you are validating spi slave device which might not have reset port, so initially you can just check the default state on spi line like weak pull up/down or 'Z', then start driving signal with different opcodes. I Hope that helps!! If i still not clear, please let me know. Regards /Ruchir Hongnhattl 1 Quote
Hongnhattl Posted September 1, 2015 Author Report Posted September 1, 2015 Reset @ DUT : during hard reset DUT or any digital design will restore to its initial predefined condition. which means all internal register, fifo, state machines are reset to its predefine or known state, or in short to its reset state. In addition to this, all output port are also reset`d, which means verification engg also need to check the reset value of output port using assertions( which i normally do or suggest ) apart from register values. Reset model : to apply reset you can create a interface which contain all reset signals (as some design have more than 1 reset signal+ test reset signals). This reset interface handle passed to your uvm_env by config_db. And finally in your uvm_env you can create task api which controls the reset with predefined intial state. Now test can call this reset API to drive reset condition as per requirement with time as parameter. CAUTION : If you want to apply reset multiple times during same simulation cycle, then you must take care of sequence should not block any sequencer. And reset information should be pass to all agent. so to answer your query regarding new reset agent, i would suggest a task would gives more flexibility and assertions will help in checking default state of DUT signals(so no need to create separate scoreboard). Im also assuming in your case you are validating spi slave device which might not have reset port, so initially you can just check the default state on spi line like weak pull up/down or 'Z', then start driving signal with different opcodes. I Hope that helps!! If i still not clear, please let me know. Regards /Ruchir Hi Ruchir Thanks for yor help a lot. Thanks to your suggestion, I have found this useful example for reset agent http://forums.accellera.org/files/file/111-cadence-reset-example-and-package/ Let me ask one more question. I'm verifying for a read opcode of a SPI memory device DUT. The memory address boundary is from 0 to 0x3FFFFF. The memory is modeled as a file that contains the data pattern for the memory. The address is split into Page address and Byte address, each page has 256 bytes. To read the data, I need to send out the command: one byte opcode + four byte of Address + dummy bytes. The DUT then gets into a continuous read mode, it means it keeps shifting the data output as long as the Chip select signal is still asserted. From this we can see that, the number of data output is however we want. This makes me think a lot how to cover for this. How should I define the coverage point for the number of data output? Besides, Should I verify for every address of the memory and what kind of data pattern I need to cover? Could you and anyone else help me? Thanks and best regards, Nhat Quote
ruchir.bharti Posted September 4, 2015 Report Posted September 4, 2015 Hey Nhat, Thanks for sending reset agent link, I haven't check it all but looks good. Regarding Coverage on SPI protocol, to my best understanding there are 9 parameters through which we can complete SPI interface coverage : 1) Operation direction - { IN, OUT} // Direction wrt to memory device. 2) Operation on - { MEMORY, REGISTER} // memory or device register operation 3) PAD - { SINGLE, DUAL, QUAD, OCTA} // pad in use during operation 4) operation flow - { OPC, ADDR, DUMMY, MODE, DATA} // 5) data size - { SMALL_PAGE, SINGLE_PAGE, MULTI_PAGE} // small_page == {1-255 bytes}, single_page == 256 bytes, multi page == 256 x n[2-10] 6) addr size - { 3BYTE, 4BYTE} // 7) addr pointer - { START, MIDDLE, END, RANDOM} // address pointer 8) addr alignment - { PAGE_ALIGNED, PAGE_UNALIGNED} // address is page aligned or not 9) edge type - { SDR, DDR} // Single edge data capture or Dual edge From above enum, you can customize your stimulus generation and protocol coverage. I hope that would help you. Regards /Ruchir Quote
Hongnhattl Posted September 4, 2015 Author Report Posted September 4, 2015 Hey Nhat, Thanks for sending reset agent link, I haven't check it all but looks good. Regarding Coverage on SPI protocol, to my best understanding there are 9 parameters through which we can complete SPI interface coverage : 1) Operation direction - { IN, OUT} // Direction wrt to memory device. 2) Operation on - { MEMORY, REGISTER} // memory or device register operation 3) PAD - { SINGLE, DUAL, QUAD, OCTA} // pad in use during operation 4) operation flow - { OPC, ADDR, DUMMY, MODE, DATA} // 5) data size - { SMALL_PAGE, SINGLE_PAGE, MULTI_PAGE} // small_page == {1-255 bytes}, single_page == 256 bytes, multi page == 256 x n[2-10] 6) addr size - { 3BYTE, 4BYTE} // 7) addr pointer - { START, MIDDLE, END, RANDOM} // address pointer 8) addr alignment - { PAGE_ALIGNED, PAGE_UNALIGNED} // address is page aligned or not 9) edge type - { SDR, DDR} // Single edge data capture or Dual edge From above enum, you can customize your stimulus generation and protocol coverage. I hope that would help you. Regards /Ruchir Hi Ruchir, Your answer is a good direction, based on this I know what I need to cover. This is helpful to me. I appreciate that. But one thing I still unclear is that regarding to the data size, as I see on the comment words multi page == 256 x n[2-10], if so the maximum data size of SPI protocol is 10 pages per one transfer. For my DUT, If I want to take larger data size, I need to start multiple read operation. Is that correct? Best regards, Nhat Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.