题解 | 基础版09#使用子模块实现三输入数的大小比较#
使用子模块实现三输入数的大小比较
http://www.nowcoder.com/practice/bfc9e2f37fe84c678f6fd04dbce0ad27
module的使用和例化,这个题的问题主要集中在为什么使用2个子模块不对,用3个才对。
实际上,对于组合逻辑实现的子模块,可以用2个,但是要打两拍才和给的波形一致。
对于时序逻辑实现的子模块,更值得大家仔细思考一下波形时序,2个确实不对,发生了比较错位,下面将详细说明。
1. 题目
在数字芯片设计中,通常把完成特定功能且相对独立的代码编写成子模块,在需要的时候再在主模块中例化使用,以提高代码的可复用性和设计的层次性,方便后续的修改。
请编写一个子模块,将输入两个8bit位宽的变量data_a,data_b,并输出data_a,data_b之中较小的数。并在主模块中例化,实现输出三个8bit输入信号的最小值的功能。
输入描述:
clk:系统时钟
rst_n:异步复位信号,低电平有效
a,b,c:8bit位宽的无符号数
输出描述:
d:8bit位宽的无符号数,表示a,b,c中的最小值
2. 解析
2.1 module模块
一个.v文件中可以写多个模块module(一般是一个文件写一个module),其中主模块的名字和.v文件名相同。
module模块名( 端口描述 ); ... endmodule
例化:
模块名例化名( 端口参数传递(按位置或者按名字均可) );比如模块名是“人”,例化名可以起名为“张三”、“李四”,这样就例化了2个“人”。
2.2 为什么调用两个子模块就不对
两种情况:
(1)子模块是纯组合逻辑
如果你的子模块用的全部是组合逻辑实现的比较,那么可以使用2个子模块,和波形不对应的原因在于提前了1个时钟。使用2个组合逻辑得到最小值后,再主模块里要对这个值打两拍,这样时序和题目答案的波形一致。
(2)子模块是时序逻辑
子模块里面的比较也选择时序逻辑寄存输出。
先说使用三个子模块的做法,a、b比较,在T+1时刻输出最小值tmp1,同时a、c比较在T+1时刻得到最小值tmp2,然后是tmp1和tmp2比较在T+2时刻得到最小值d;
如果是使用2个子模块,T时刻比较a、b,在T+1时刻输出最小值tmp1,然后T+1时刻比较时才是c和tmp1比,在T+2时刻得到T+1时的c和tmp1的最小值;
注意,这样比较完就是拿T时刻的a、b和T+1时刻的c比较!
3. 代码
3.1组合逻辑子模块
`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] 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&nbs***bsp;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( input [7:0]a, input [7:0]b, output [7:0]d ); assign d = (a>b) ? b : a; endmodule
3.2时序逻辑子模块
`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] tmp1; // a b 的最小值 child_mod U0( .clk ( clk ), .rst_n ( rst_n ), .a ( a ), .b ( b ), .d ( tmp1 ) ); wire [7:0] tmp2; // a c 的最小值 child_mod U1( .clk ( clk ), .rst_n ( rst_n ), .a ( tmp1 ), .b ( c ), .d ( tmp2 ) ); child_mod U2( .clk ( clk ), .rst_n ( rst_n ), .a ( tmp1 ), .b ( tmp2 ), .d ( d ) ); reg [7:0] d_reg; always @ (posedge clk&nbs***bsp;negedge rst_n) begin if( ~rst_n ) begin d_reg <= 8'b0; end else begin d_reg <= tmp2; end end assign d = d_reg; endmodule module 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&nbs***bsp;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; endmodule