UVM Register Model Example
In the previous few articles, we have seen what a register model is and how it can be used to access registers in a given design. Let us see a complete example of how such a model can be written for a given design, how it can be integrated into the environment and how it can be used to write and read into design fields.
Click here to refresh the concept on register models !
The following design has the following registers and fields that are accessible through an APB interface. The design essentially represents a traffic light controller which can be configured by writing into certain control registers.
The ctl register contains fields to start the module, and configure it to be in the blink yellow or blink red mode. The state register is read-only and returns current state of the design - yellow, red or green. The two timer registers stores the time between transition from each state. The profile bit allows the user to choose between the two programmed timer values. This can be useful for peak and off-peak times.
This is not a complete design since our purpose is simply to show how registers in this design can be read/written using a UVM register model. All the signals listed as the module ports belong to APB specification.
module traffic ( input pclk, input presetn, input [31:0] paddr, input [31:0] pwdata, input psel, input pwrite, input penable, // Outputs output [31:0] prdata); reg [3:0] ctl_reg; // profile, blink_red, blink_yellow, mod_en RW reg [1:0] stat_reg; // state[1:0] reg [31:0] timer_0; // timer_g2y[31:20], timer_r2g[19:8], timer_y2r[7:0] RW reg [31:0] timer_1; // timer_g2y[31:20], timer_r2g[19:8], timer_y2r[7:0] RW reg [31:0] data_in; reg [31:0] rdata_tmp; // Set all registers to default values always @ (posedge pclk) begin if (!presetn) begin data_in <= 0; ctl_reg <= 0; stat_reg <= 0; timer_0 <= 32'hcafe_1234; timer_1 <= 32'hface_5678; end end // Capture write data always @ (posedge pclk) begin if (presetn & psel & penable) if (pwrite) case (paddr) 'h0 : ctl_reg <= pwdata; 'h4 : timer_0 <= pwdata; 'h8 : timer_1 <= pwdata; 'hc : stat_reg <= pwdata; endcase end // Provide read data always @ (penable) begin if (psel & !pwrite) case (paddr) 'h0 : rdata_tmp <= ctl_reg; 'h4 : rdata_tmp <= timer_0; 'h8 : rdata_tmp <= timer_1; 'hc : rdata_tmp <= stat_reg; endcase end assign prdata = (psel & penable & !pwrite) ? rdata_tmp : 'hz; endmodule
Let us declare an interface with signals in the APB protocol and this interface can be passed to the testbench as a virtual interface for the driver to drive some values to the design. To keep things simple, let us not declare clocking blocks and modports, although they are recommended in a real project.
interface bus_if (input pclk); logic [31:0] paddr; logic [31:0] pwdata; logic [31:0] prdata; logic pwrite; logic psel; logic penable; logic presetn; endinterface