将通过验证一个简单的设计:TinyALU来检查UVM。这样做,可以将精力集中在测试台上,而不会因DUT的复杂性而分心。
上图为TinyALU的框图,ALU在时钟的上升沿工作。当start为1时,TinyALU从A和B总线上读取操作数,从op总线上读取一个操作数,并基于该操作数的结果进行运算。操作可能需要任意数量的周期。
当操作完成时,输出done为1。reset_n信号是有效的低电平同步复位。
TinyALU有五种操作:NOP、ADD、AND、XOR和MULT。用户在请求计算时对三位运算总线上的操作进行编码,其中NOP为空指令。以下是编码:
以下是TinyALU的波形:
start信号必须保持高电平,运算符和操作数必须保持稳定,直到TinyALU产生完成信号。done信号仅在一个时钟内保持高电平。NOP操作上没有done信号。在NOP上,升高start信号一个周期后降低。
我们将通过创建TinyALU的常规测试台来开始我们的UVM之旅。然后,每一章都将修改测试台,使其符合UVM。
TinyAlu的rtl代码分为三个部分:tinyalu、single_cycle、three_cycle。
module tinyalu (input [7:0] A,//输入A
input [7:0] B,//输入B
input [2:0] op,//opcode对应不同的operation
input clk,//时钟
input reset_n,//复位
input start,//start信号
output done,//done信号
output [15:0] result//输出结果);
wire [15:0] result_aax, result_mult;//对应后面single_cycle和three_cycle的输出结果
wire start_single, start_mult;//对应后面single_cycle和three_cycle的start信号
assign start_single = start & ~op[2];
//single_cycle的start需要总start和op[2]对应的位为0,因为single_cycle对应op的第3位均为0
assign start_mult = start & op[2];
//three_cycle的start需要总start和op[2]对应的位为1,因为single_cycle对应op的第3位均为1
single_cycle and_add_xor (.A, .B, .op, .clk, .reset_n, .start(start_single),
.done(done_aax), .result(result_aax));
//模块例化,例化single_cycle的module
three_cycle mult (.A, .B, .op, .clk, .reset_n, .start(start_mult),
.done(done_mult), .result(result_mult));
//模块例化,例化three_cycle的module
assign done = (op[2]) ? done_mult : done_aax;
//done信号赋值,op最高位为1时,done输出done_mult,op最高位为0时,done输出done_aax,两个信号分别对应three_cycle和single_cycle的done信号
assign result = (op[2]) ? result_mult : result_aax;
//原理同done信号
endmodule // tinyalu
module single_cycle(input [7:0] A,
input [7:0] B,
input [2:0] op,
input clk,
input reset_n,
input start,
output logic done,
output logic [15:0] result);
always @(posedge clk)
if (!reset_n) //复位
result <= 0;
else
case(op) //用case分支语句完成operation的操作
3'b001 : result <= A + B; //add
3'b010 : result <= A & B; //and
3'b011 : result <= A ^ B; //xor
endcase // case (op)
always @(posedge clk)
if (!reset_n)
done <= 0; //done信号复位
else
done = ((start == 1'b1) && (op != 3'b000));
//start信号为1并且operation不是NOP时,done信号输出为高
endmodule : single_cycle
module three_cycle(input [7:0] A,
input [7:0] B,
input [2:0] op,
input clk,
input reset_n,
input start,
output logic done,
output logic [15:0] result);
logic [7:0] a_int, b_int;
logic [15:0] mult1, mult2;
logic done1, done2, done3;
always @(posedge clk)
if (!reset_n) begin //复位
done <= 0;
done3 <= 0;
done2 <= 0;
done1 <= 0;
a_int <= 0;
b_int <= 0;
mult1 <= 0;
mult2 <= 0;
result<= 0;
end else begin // if (!reset_n)
a_int <= A; //输入
b_int <= B; //输入
mult1 <= a_int * b_int; //multiply
mult2 <= mult1; //流水线传输 相当于DFF
result <= mult2; //流水线传输 相当于DFF
done3 <= start & !done; //start信号为1并且done信号为0时done3为1
done2 <= done3 & !done; //此处的done3信号相当于start
done1 <= done2 & !done;
done <= done1 & !done;
end // else: !if(!reset_n)
endmodule : three_cycle