《The UVM Primer》——Chapter1: Introduction and DUT

2023-10-18 04:59

本文主要是介绍《The UVM Primer》——Chapter1: Introduction and DUT,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 引言

《The UVM Primer》 是 一本UVM 的入门书籍,由Ray Salemi编写出版,并且是免费开源的项目,代码可以在GitHub上下载。这本书只有一百多页的篇幅,围绕TinyALU进行一步步的深入学习,非常适合初学UVM的新手。当然也需要有SystemVerilog的相关基础。

本书的UVM需要了解以下几个基本概念:

  • SystemVerilog 的面向对象OOP

  • 动态生成的对象,可在不重新编译的情况下指定tests和testbench架构

  • 由 Agent, Driver, Monitor 和 BFM 构成的分层的testbench

  • 对象之间的事务级通信(TLM)

  • Testbench激励(UVM Sequences)与testbench结构的分离


2. DUT

本项目将通过一个简单的DUT即TinyALU,来对UVM展开学习,重点是在验证平台上,而不是设计本身。TinyALU是 VHDL 编写的一个简单的 ALU,它接收两个 8 位数据(A 和 B),并产生 16 位的输出 result。这里是 TinyALU 的顶层:

ALU在时钟上升沿采样,当 start 信号有效时, TinyALU将从 A、B总线上读取操作数, 从 op 总线上读取指令, 然后根据指令生成结果。指令可以是任意长度时钟周期的。TinyALU 在指令完成的时,拉高 done 信号。

reset_n 信号是低有效, 同步的复位信号。

TinyALU有5个指令: NOP、ADD、AND、XOR和MULT。在计算的时候,需对 3 位总线 op 进行编码,编码表如下:

Here is the waveform for the TinyALU:

start 信号需要保持为高, 操作码和操作数在 TinyALU 拉高 done 信号之前,都要保持稳定。done 信号只拉高一个时钟周期。NOP 指令没有 done 信号。在 NOP 中, requester 在 start 信号为高一个周期后将其拉低。


后续章节将依次搭建验证环境平台,每章都会做些改动,使得它变得越来越UVM!

附上Tiny ALU的一些源代码:

// tinyalu.v
module tinyalu(A, B, clk, op, reset_n, start, done, result, bus_valid, bus_op, bus_addr, bus_wr_data, bus_rd_data);input [7:0]      A;input [7:0]      B;input            clk;input [2:0]      op;input            reset_n;input            start;output           done;output [15:0]    result;input            bus_valid;input            bus_op;input [15:0]     bus_addr;input [15:0]     bus_wr_data;output reg[15:0]    bus_rd_data;wire             done_aax;wire             done_mult;wire [15:0]      result_aax;wire [15:0]      result_mult;reg              start_single;reg              start_mult;reg              done_internal;reg[15:0]        result_internal;reg [15:0]       ctrl_reg;reg [15:0]       status_reg;//start_demuxalways @(op[2] or start) begincase (op[2])1'b0 :beginstart_single <= start;start_mult <= 1'b0;end1'b1 :beginstart_single <= 1'b0;start_mult <= start;enddefault:;endcaseend//result_muxalways @(result_aax or result_mult or op) begincase (op[2])1'b0 :result_internal <= result_aax;1'b1 :result_internal <= result_mult;default :result_internal <= {16{1'bx}};endcaseend//done_muxalways @(done_aax or done_mult or op) begincase (op[2])1'b0 :done_internal <= done_aax;1'b1 :done_internal <= done_mult;default :done_internal <= 1'bx;endcaseend//bus writealways @(posedge clk)beginif(!reset_n)beginctrl_reg <= 16'h0;status_reg <= 16'h0;endelse if(bus_valid && bus_op)begincase(bus_addr)16'h8:beginctrl_reg <= bus_wr_data;enddefault:;endcaseendif(ctrl_reg[1])beginif(A == 8'hff)status_reg[0] <= 1'b1;elsestatus_reg[0] <= 1'b0;if(B == 8'hff)status_reg[1] <= 1'b1;elsestatus_reg[1] <= 1'b0;if(A == 8'h00)status_reg[2] <= 1'b1;elsestatus_reg[2] <= 1'b0;if(B == 8'h00)status_reg[3] <= 1'b1;elsestatus_reg[3] <= 1'b0;endend//bus readalways @(posedge clk)beginif(!reset_n)bus_rd_data <= 16'h0;else if(bus_valid && !bus_op)begincase(bus_addr)16'h8:beginbus_rd_data <= ctrl_reg;end16'h9:beginbus_rd_data <= status_reg;enddefault:beginbus_rd_data <= 16'h0;endendcaseendendsingle_cycle add_and_xor(.A(A), .B(B), .clk(clk), .op(op), .reset_n(reset_n), .start(start_single), .done_aax(done_aax), .result_aax(result_aax));three_cycle mult(.A(A), .B(B), .clk(clk), .reset_n(reset_n), .start(start_mult), .done_mult(done_mult), .result_mult(result_mult));assign result = (ctrl_reg[0])? ~result_internal : result_internal;assign done = done_internal;endmodule

// single_cycle_add_and_xor.v
module single_cycle(A, B, clk, op, reset_n, start, done_aax, result_axx);input [7:0]			A;input [7:0]			A;input 				clk;input [2:0]			op;input 				reset_n;input 				start;output reg			done_axx;outpit reg[15:0]	result_axx;//single_cycle_opsalways @(posedge clk) beginif(!reset_n)result_aax <= 16'd0;else beginif (start == 1'b1)begincase (op)3'b001 :result_aax <= ({8'b00000000, A}) + ({8'b00000000, B});3'b010 :result_aax <= (({8'b00000000, A}) & ({8'b00000000, B}));3'b011 :result_aax <= (({8'b00000000, A}) ^ ({8'b00000000, B}));default :;endcaseendelse ;endend//set_donealways @(posedge clk or negedge reset_n) beginif (!reset_n)done_aax <= 1'b0;else beginif ((start == 1'b1) && (op != 3'b000) && (done_aax == 1'b0))done_aax <= 1'b1;elsedone_aax <= 1'b0;endendendmodule

// three_cycle_mult.v
module three_cycle(A, B, clk, reset_n, start, done_mult, result_mult);input [7:0]      A;input [7:0]      B;input            clk;input            reset_n;input            start;output           done_mult;output reg[15:0]    result_mult;reg [7:0]        a_int;reg [7:0]        b_int;reg [15:0]       mult1;reg [15:0]       mult2;reg              done3;reg              done2;reg              done1;reg              done_mult_int;//multiplieralways @(posedge clk or negedge reset_n) beginif (!reset_n) begindone_mult_int <= 1'b0;done3 <= 1'b0;done2 <= 1'b0;done1 <= 1'b0;a_int <= 8'd0;b_int <= 8'd0;mult1 <= 16'd0;mult2 <= 16'd0;result_mult <= 16'd0;endelse begina_int <= A;b_int <= B;mult1 <= a_int * b_int;mult2 <= mult1;result_mult <= mult2;done3 <= start & ((~done_mult_int));done2 <= done3 & ((~done_mult_int));done1 <= done2 & ((~done_mult_int));done_mult_int <= done1 & ((~done_mult_int));endendassign done_mult = done_mult_int;endmodule

这篇关于《The UVM Primer》——Chapter1: Introduction and DUT的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/230330

相关文章

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

UVM:callback机制的意义和用法

1. 作用         Callback机制在UVM验证平台,最大用处就是为了提高验证平台的可重用性。在不创建复杂的OOP层次结构前提下,针对组件中的某些行为,在其之前后之后,内置一些函数,增加或者修改UVM组件的操作,增加新的功能,从而实现一个环境多个用例。此外还可以通过Callback机制构建异常的测试用例。 2. 使用步骤         (1)在UVM组件中内嵌callback函

【C++ Primer Plus习题】12.2

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "String.h"using namespace std;int main(){String s1(" and I am a

【C++ Primer Plus习题】12.1

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "Cow.h"using namespace std;int main(){Cow c1;Cow c2("老母牛", "喝奶"

《C Primer Plus》第10 章复习题和编程练习

目录 一、复习题二、编程练习 一、复习题 1. 下面的程序将打印什么内容? #include <stdio.h>int main(){int ref[] = {8, 4, 0 ,2};int *ptr;int index;for (index = 0, ptr = ref; index < 4; index++, ptr++){printf("%d %d\n", ref[in

AI基础 L1 Introduction to Artificial Intelligence

什么是AI Chinese Room Thought Experiment 关于“强人工智能”的观点,即认为只要一个系统在行为上表现得像有意识,那么它就真的具有理解能力。  实验内容如下: 假设有一个不懂中文的英语说话者被关在一个房间里。房间里有一本用英文写的中文使用手册,可以指导他如何处理中文符号。当外面的中文母语者通过一个小窗口传递给房间里的人一些用中文写的问题时,房间里的人能够依

[UVM]6.component driver monitor sequencer agent scoreboard env test

1.知识点回顾 (1)component需要有parent,因为参加构成组件,所以需要(继承); (2)object与component之间间隔report_object。 2.组件家族 (1)构建寄存器模型 :uvm_reg_predictor;激励器:driver/random_stimulus/sequencer_base/sequencer;监测器:monitor;

Introduction to Deep Learning with PyTorch

1、Introduction to PyTorch, a Deep Learning Library 1.1、Importing PyTorch and related packages import torch# supports:## image data with torchvision## audio data with torchaudio## text data with t

【C++ Primer Plus习题】11.6

问题: 解答: main.cpp #include <iostream>#include "Stonewt.h"using namespace std;const int SIZE = 6;int main(){Stonewt stone_arr[SIZE] = { 253.6,Stonewt(8,0.35),Stonewt(23,0) };double input;Ston

【C++ Primer Plus习题】10.5

问题: 解答: main.cpp #include <iostream>#include "Stack.h"using namespace std;int main(){Stack stack;customer cust;double sum_payment = 0;char select;cout << "a:入栈 p:出栈 q:退出";while (cin.get(sele