题目描述
在数字芯片设计中,通常把完成特定功能且相对独立的代码编写成子模块,在需要的时候再在主模块中例化使用,以提高代码的可复用性和设计的层次性,方便后续的修改。
请编写一个子模块,将输入两个8bit位宽的变量data_a,data_b,并输出data_a,data_b之中较小的数。并在主模块中例化,实现输出三个8bit输入信号的最小值的功能。
子模块的信号接口图如下:
主模块的信号接口图如下:
输入描述:
clk:系统时钟
rst_n:异步复位信号,低电平有效
a,b,c:8bit位宽的无符号数
输出描述:
d:8bit位宽的无符号数,表示a,b,c中的最小值
代码实现方式1
使用时序逻辑子模块
需要调用3个模块,其中:第一个模块:比较 T 时刻的 a 和 b,T+1 时刻出来 tmp1; 第二个模块:比较 T 时刻的 a 和 c,T+1 时刻出来 tmp2; 第三个模块:比较 T+1 时刻的 tmp1 和 tmp2,T+2 时刻出来 d;
如果只用2个子模块,那么 T 时刻比较 a 和 b 得到 tmp1,再比较 tmp1 和 c 的时候是 T+1 时刻的 c和 T+1 时刻的 tmp1,而 tmp1 代表的是 T 时刻 a 和 b 的较小值,所以这时候比较的 T 时刻的 a、b和 T+1 时刻的 c,显然不符合要求。
`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
);
//*************code***********//
// T 时刻的 a 和 b,T+1 时刻出来 tmp1
wire [7:0] tmp1; // a b 的最小值
child_mod U0(
.clk ( clk ),
.rst_n ( rst_n ),
.a ( a ),
.b ( b ),
.d ( tmp1 )
);
// T 时刻的 a 和 c,T+1 时刻出来 tmp2
wire [7:0] tmp2; // a c 的最小值
child_mod U1(
.clk ( clk ),
.rst_n ( rst_n ),
.a ( a ),
.b ( c ),
.d ( tmp2 )
);
// T+1 时刻的 tmp1 和 tmp2,T+2 时刻出来 d
child_mod U2(
.clk ( clk ),
.rst_n ( rst_n ),
.a ( tmp1 ),
.b ( tmp2 ),
.d ( d )
);
endmodule
// 子模块
module child_mod( //child_mod模块中包含时序逻辑
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
output [7:0]d
);
reg [7:0] d_reg;
always @ (posedge clk or negedge rst_n)
begin
if( ~rst_n ) begin
d_reg<= 8'b0;
end
else begin
if( a > b )
d_reg<= b;
else
d_reg<= a;
end
end
assign d = d_reg;
//*************code***********//
endmodule
代码实现方式2
使用组合逻辑子模块,需要打两拍。
组合逻辑的子模块,就不存在时序逻辑中的延时问题,所以调用的时候用2个子模块就可以完成3个数的比较,为了符合时序波形的要求,多打一拍
关于FPGA中“打一拍”的含义,我们可以理解为把某个信号延迟了一个时钟周期。“打两拍”就是延迟两个时钟周期,即打一拍就是系统时钟对外部信号采样一次,把采样的结果数据做为下一步的控制状态
如果是使用2个子模块,
T时刻比较a、b,在T+1时刻输出最小值tmp1,在T+2时刻得到T+1时的c和T+1时的tmp1的最小值;
注意,这样比较完就是拿T时刻的a、b和T+1时刻的c比较
`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
);
//*************code***********//
wire [7:0] tmp1; // a b 的最小值
child_mod U0(
.a ( a ),
.b ( b ),
.d ( tmp1 )
);
wire [7:0] tmp2; // a c 的最小值
child_mod U1(
.a ( tmp1 ),
.b ( c ),
.d ( tmp2 )
);
reg [7:0] d_reg;
reg [7:0] d_reg2;
always @ (posedge clk or negedge rst_n)
begin
if( ~rst_n ) begin
d_reg <= 8'b0;
d_reg2 <= 8'b0;
end
else begin
d_reg <= tmp2; //为了符合时序波形的要求,多打一拍
d_reg2 <= d_reg;
end
end
assign d = d_reg2;
endmodule
module child_mod( //child_mod模块中只有组合逻辑
input [7:0]a,
input [7:0]b,
output [7:0]d
);
assign d = (a>b) ? b : a;
//*************code***********//
endmodule