自学内容网 自学内容网

简易CPU设计入门:验证取指令模块【未完成】

项目代码下载

还是请大家首先准备好本项目所用的源代码。如果已经下载了,那就不用重复下载了。如果还没有下载,那么,请大家点击下方链接,来了解下载本项目的CPU源代码的方法。

下载本项目代码

准备好了项目源代码以后,我们接着去讲解。

本节前言

想要学习本节,前提是,你得是学习过我讲解取指令模块的有关章节。最好呢,你是从本系列专栏的开头,连续地,学习到这里的。否则,知识不完整,你也不知道哪里落下了,即使你来问我,我可能也不知道,你究竟是差在哪里未理解。

下面的四个链接,是我讲解取指令模块的四篇文章。

取指令(一)

取指令(二)

取指令(三)

取指令(四)

以上的四个讲解取指令模块的文章,建议没有学习的同学,还是先去学习一下。如果你学完完了上述的内容,那么,我们可以继续本文的学习。

取指令模块,它指的是【cpu_me01\code\get_instruct.v】代码文件中的模块。取指令模块的代码,我就不贴了。

验证取指令模块的代码,我这里已经是写好了,我来将其内容给贴在下面的代码块中。

`timescale 1ns/1ns
module tb_get_instruct();
reg sys_clk;
reg sys_rst_n;
reg get_inst_en;
reg [15:0] ip;
wire decode_en;
wire [15:0] instruct_code;

wire [15:0] ip_buf;
wire [15:0] instruct_code_wire;
wire rd_en;
wire rd_en_d1;
wire rd_en_d2;

reg [9:0] cnt;

assign ip_buf = get_instruct_inst.ip_buf;
assign instruct_code_wire = get_instruct_inst.instruct_code_wire;
assign rd_en = get_instruct_inst.rd_en;
assign rd_en_d1 = get_instruct_inst.rd_en_d1;
assign rd_en_d2 = get_instruct_inst.rd_en_d2;

initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#60
sys_rst_n <= 1'b1;
end

always #10 sys_clk = ~sys_clk;

always @(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
cnt <= 10'd0;
else if (cnt < 10'd20)
cnt <= cnt + 10'd1;
else
cnt <= cnt;

always @(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n == 1'b0)
begin
get_inst_en <= 1'b0;
ip <= 16'h0000;
end
else if (cnt == 10'd3)
begin
get_inst_en <= 1'b1;
ip <= 16'h0002;
end
else
begin
get_inst_en <= 1'b0;
ip <= 16'h0000;
end

get_instruct get_instruct_inst(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.get_inst_en(get_inst_en),
.ip(ip),
.decode_en(decode_en),
.instruct_code(instruct_code)
);

endmodule

以上,是验证取指令模块的代码内容了。接下来,我就来讲解代码。

代码讲解

图1

图1中的代码,是验证模块的前14行的内容。其中,第1行,这个是规定了本仿真验证模块使用的时间尺度。在【1ns/1ns】这部分语句中,左边的【1ns】代表着,本模块的1个时间单位,是1ns。右边的【1ns】用于指定仿真过程中进位取整的精度为1ns。

需要注意的是,如下的写法是错误的。

`timescale 60ns/3ns

这是因为,无论是左边的指定时间单位的数值,还是右边的指定时间精度的数值,只能采用1、10或者100,两边的数值可以相同,也可以不同。

第2行,是规定了本模块的模块名。我们的取指令模块的模块名是【get_instruct】,那么,对该模块的验证,就是在它的前面,加上【tb_】前缀,变为【tb_get_instruct】。

一般地,我们想要验证的模块是什么名字,验证该模块的模块名,都是在被验证模块的前面加上【tb_】前缀。

第3行到第8行,它们对应着取指令模块的输入输出端口。其实我在写仿真验证代码的时候,就是将取指令模块的输入输出端口给复制过来的。复制过来以后,将端口类型【input wire】或者【input】修改为【reg】,将【output wire】或者【output】修改为【wire】,就可以了。

我们可以来看一看取指令模块的端口声明部分。

图2,取指令模块的端口声明部分

我们将图2的3到9行,与图1的3到8行做一个对比,就会明白【tb_get_instruct】模块的3到8行的写法了。

我们再回到图1里面。图1的10到14行,声明了几个wire型变量,这几个变量,其实在取指令模块里面都有。我们在图1里面,也就是在【tb_get_instruct】模块里面声明这几个变量,其实是为了将验证模块与取指令模块的对应变量连接起来,以观测取指令模块中相应变量的波形变化情况。

我们来看一看取指令模块声明的几个变量。

图3,取指令模块声明的几个变量

在图3中,可以看到,在取指令模块中声明的几个变量,有reg型的,也有wire型的。而在图1的10到14行,我们声明的同名变量,均为wire型的。这是因为,我们在验证模块中声明的变量,是为了与取指令模块中的相应变脸连接起来,实时地观察取指令模块中对应变量的值。想要实现实时观测的效果,而没有仿真的延迟,那么,在仿真验证模块中,我们就需要用wire型变量,来连接取指令模块中的对应变量。

一般来讲,我们若是想要在test bench文件中观测被验证模块中的某一个变量,我们就需要再test bench中声明一个wire型变量,并且用连续赋值语句将验证模块与被验证模块中的相应的变量连接起来。wire型变量,它具备着实时性,可以用来实时观测。

既然提到了连续赋值语句,而且,我们在图1中的10到14行声明几个wire型变量,正是为了与取指令模块中的对应同名变量相连接,那么,我们肯定是在test bench中,用到了连续赋值语句。那么,我们就来看一看我们的连续赋值语句。如下面的代码块所示。

assign ip_buf = get_instruct_inst.ip_buf;
assign instruct_code_wire = get_instruct_inst.instruct_code_wire;
assign rd_en = get_instruct_inst.rd_en;
assign rd_en_d1 = get_instruct_inst.rd_en_d1;
assign rd_en_d2 = get_instruct_inst.rd_en_d2;

上面的代码块,都用到了【tb_get_instruct】模块中所实例化的取指令模块的模块名,【get_instruct_inst】。实例化取指令模块的代码,我们一会儿再看。

从上面的代码块,我们看到,我们的确是通过连续赋值语句,将本验证模块【tb_get_instruct】中的几个变量与取指令模块中的同名变量给连接起来了。

接下来呢,我们再来看一看验证模块中,实例化取指令模块的代码。如下图所示。

图4

图4的写法,其实,也就是一种套路写法。第59行,是模块与实例名。第60行到65行,是【get_instruct】模块与本验证模块【tb_get_instruct】的变量连接情况。写这个变量连接的代码的时候,我是将取指令模块的端口声明部分,给复制过来,然后呢,将端口类型给去掉,把【[15:0]】等等的向量类型也给去掉,仅仅留下端口名。然后呢,在每一个端口名前面加上英文的句点符号。然后呢,每一行的端口右边加上括号,括号内写上本模块的要连接的变量名。

一般地,我去写验证模块的时候,我都将验证模块与被验证模块的连接变量设置为相同的名称。当然了,随着代码复杂度的增加,免不了地,以后,会有被验证模块的端口名与验证模块的连接变量名不一致的情况。

在写实例化代码的时候,在初学阶段,究竟是否要将验证模块的连接变量与被验证模块的端口名设置为相同,这个你自己来决定。我的建议是,你在跟着哪本书或者哪个教程来学习,你就先学习哪种写法。

在我们的专栏里面,在写实例化代码的时候,我倾向于,将被验证模块的端口名与验证模块的连接变量设置为相同的名称。

在图4里面,写完了实例化代码以后,在68行,是【endmodule】字样。也就是,实例化代码,位于【tb_get_instruct】的最后面的位置。

一般地,书写 test bench 代码文件的时候,实例化代码,都是写在最后的位置。至少我这里是这样子来写的。你当然可以自由地设置其书写位置,不过,我确实是这么来写的。貌似,我在学习FPGA开发版的配套教程的时候,里面也是这么写的。

某些个一般的通行的惯例,大家跟着照做就可以了。


原文地址:https://blog.csdn.net/2401_82825368/article/details/142884909

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!