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;

一定注意这个同时的含义。T时刻输入a、b、c,T+1时刻得到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