前言
今天我们做的是第九道题——使用子模块实现三输入数的大小比较,在这道题中我们需要清楚的知识点是如何去声明一个子模块,并且在主模块中将其实例化。接下来我们开始解这道题。使用子模块实现三输入数的大小比较
一、题目描述
在数字芯片设计中,通常把完成特定功能且相对独立的代码编写成子模块,在需要的时候再在主模块中例化使用,以提高代码的可复用性和设计的层次性,方便后续的修改。
请编写一个子模块,将输入两个8bit位宽的变量data_a,data_b,并输出data_a,data_b之中较小的数。并在主模块中例化,实现输出三个8bit输入信号的最小值的功能。
子模块的信号接口图如下:
主模块的信号接口图如下:
输入描述:
clk:系统时钟
rst_n:异步复位信号,低电平有效
a,b,c:8bit位宽的无符号数
输出描述:
d:8bit位宽的无符号数,表示a,b,c中的最小值
二、实现思路
1.模块的实例化
模块的实例化就是在一个模块中引用另一个模块,对其端口进行连接,模块的实例化建立了描述的层次。信号端口可以通过位置或名称关联,下面介绍端口的两种连接方式:
1)命名端口连接
这种方法将需要例化的模块端口与外部信号按照其名字进行连接,端口顺序随意,可以与引用 module 的声明端口顺序不一致,只要保证端口名字与外部信号匹配即可。
格式为:
mod_a instance2 (
.out(wc),
.in1(wa),
.in2(wb)
);
2)顺序端口连接
这种方法将需要例化的模块端口按照模块声明时端口的顺序与外部信号进行匹配连接。
格式为:
mod_a instance1 ( wa, wb, wc );
3)端口连接规则
1>对于输入、输出以及输入输出双向口而言
从模块外部看
- input 端口可以连接 wire 或 reg 型变量。
- output 端口必须连接 wire 型变量
- inout 端口必须连接wire 型变量
从模块内部看
- input 端口必须是 wire 型变量。
- output 端口可以是 wire 或 reg 型变量
2>对于悬空端口而言
模块实例化时,如果某些信号不需要与外部信号进行连接交互,我们可以将其悬空,即端口例化处保留空白即可,上述例子中有提及。
output 端口正常悬空时,我们甚至可以在例化时将其删除。
input 端口正常悬空时,悬空信号的逻辑功能表现为高阻状态(逻辑值为 z)。但是,例化时一般不能将悬空的 input 端口删除,否则编译会报错。
2.具体解题思路
知道如何去实例化一个模块后,我们就要开始写题了,其实这道题还是蛮简单的,但就是有一个比较容易混淆的问题。在我们正常对三个数比较时,其实只需要比较两次就可以了,但在这道题中我们却需要比较三次,因为我们的代码是并行执行的,三个模块是同时实例化的,所以我们需要用两个中间变量 m,n 来存储两次比较的结果,最后 m,n 进行比较得出最终的结果。
三、代码展示
`timescale 1ns/1ns
module main_mod(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
input [7:0]c,
output [7:0]d
);
wire [7:0]m,n;
//先得到ab之中的较小值m
sub_mod mod_ab(
.clk(clk),
.rst_n(rst_n),
.data_a(a),
.data_b(b),
.data_c(m)
);
//先得到ac之中的较小值n
sub_mod mod_bc(
.clk(clk),
.rst_n(rst_n),
.data_a(b),
.data_b(c),
.data_c(n)
);
//最后对比mn的大小
sub_mod mod_mn(
.clk(clk),
.rst_n(rst_n),
.data_a(m),
.data_b(n),
.data_c(d)
);
endmodule
module sub_mod(
input clk,
input rst_n,
input [7:0]data_a,
input [7:0]data_b,
output reg [7:0]data_c
);
always @(posedge clk or negedge rst_n)
if(!rst_n)
data_c <= 0;
else if(data_a > data_b)
data_c <= data_b;
else
data_c <= data_a;
endmodule
总结
以上就是我在做这道题时的思路,以及代码的编写,如果还有更多更好的解法,欢迎读到这篇文章的朋友们在评论区告诉我,共同进步嘛。