UVM的基础知识大家在诸如CSDN、EETOP或者其他公众号上应该都能找到,这里就不重复介绍了,直接从怎么搭建环境开始。
对于IP验证而言,我们考虑地更多的都是模块的功能以及如何向上一级复用我们当前的验证环境,因此我们在讲述IP验证环境架构主要关注如何发送激励,如何进行check。我们在学习UVM验证环境的时候,可以暂时抛开DUT(即不需要一开始就上来验证一个很复杂的DUT),当前系列的分享就以最简单的RTL出发来验证。本RTL主要功能为通过apb配置寄存器实现对两个输入数据进行与/或/异或/同或的操作(仅用来辅助学习UVM验证环境,因此没有考虑跨时钟域的问题,都用同步时钟)。
以下是验证的RTL源码:
logic_op.v
/***********************************************
#
# Filename: logic_op.v
#
# Author: Kang Yaopeng -- 78490223@qq.com
# Description: ---
# Create: 2019-11-06 19:48:33
# Last Modified: 2019-11-06 19:48:33
***********************************************/
module logic_op(
input wire clk ,
input wire rst_n ,
input wire in_en ,
input wire[3:0] in1 ,
input wire[3:0] in2 ,
output reg [3:0] out ,
output reg out_en ,
input wire pclk ,
input wire presetn ,
input wire psel ,
input wire penable ,
input wire pwrite ,
input wire[31:0] paddr ,
input wire[31:0] pwdata ,
output reg [31:0] prdata ,
output reg pready
);
reg[1:0] logic_sel;
logic_op_reg_ctrl u_logic_op_reg_ctrl(
.clk (pclk )
,.rst_n (presetn )
,.i_psel (psel )
,.i_penable (penable )
,.i_pwrite (pwrite )
,.i_paddr (paddr )
,.i_pwdata (pwdata )
,.o_prdata (prdata )
,.o_pready (pready )
,.o_reg_logic_sel (logic_sel)
);
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
out <= 4'h0;
out_en <= 1'b0;
end
else if(in_en) begin
if(logic_sel==2'h0) begin
out <= in1 & in2;
end
else if(logic_sel==2'h1) begin
out <= in1 | in2;
end
else if(logic_sel==2'h2) begin
out <= in1 ^~ in2;
end
else begin
out <= in1 ^ in2;
end
out_en <= 1'b1;
end
else begin
out <= 4'h0;
out_en <= 1'b0;
end
end
endmodule
logic_op_reg_ctrl.v
module logic_op_reg_ctrl(
input wire clk
,input wire rst_n
,input wire i_psel
,input wire i_penable
,input wire i_pwrite
,input wire[31:0] i_paddr
,input wire[31:0] i_pwdata
,output wire[31:0] o_prdata
,output reg o_pready
,output reg[1:0] o_reg_logic_sel
);
wire i_cs, i_rd, i_wr;
wire[31:0] i_addr;
wire[31:0] i_datai;
reg [31:0] o_datao;
wire reg_0x0_we;
assign i_cs = i_psel;
assign i_wr = i_penable && i_pwrite;
assign i_rd = (!i_penable) && (!i_pwrite);
assign i_addr = i_paddr;
assign i_datai = i_pwdata;
assign o_prdata = o_datao;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) o_pready <= 1'b0;
else o_pready <= i_psel && !i_penable;
end
assign reg_0x0_we = i_cs&&i_wr&&(i_addr==32'h0);
//0x0 register
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
o_reg_logic_sel <= 2'h0;
else if(reg_0x0_we==1'b1)
o_reg_logic_sel <= i_datai[1:0];
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) o_datao <= 32'h0;
else if(i_cs&&i_rd) begin
case(i_addr)
32'h0: o_datao <= {30'h0,o_reg_logic_sel};
default: o_datao <= 32'h0;
endcase
end
end
endmodule
后续内容大家也可以关注我的公众号继续阅读