这个题是第一道分子模块的题目:
子模块有四个输入:
1、时钟信号clk
2、复位信号rst_n
3、8位数据a
4、8位数据b
一个输出:
8位数据c
子模块要完成的任务是两个数比大小,这几乎没有难度,也没什么好说的,直接把代码放出来:
module zimokuai(
	input clk,
	input rst_n,
	input [7:0]a,
	input [7:0]b,
	
	output reg [7:0] d_reg
);

always@(posedge clk or negedge rst_n)
	if(rst_n == 1'b0)
		d_reg <= 8'd0;
	else if(a < b)
		d_reg <= a;
	else
		d_reg <= b;

endmodule
这个题主要想考察的还是子模块的调用
Verilog子模块的调用相对于c还是有些麻烦的。Verilog的模块调用主要有一下几点要注意的:
1、顶层模块的所有变量都必须是wire型
    理解起来也不是很难,子模块是一个黑盒子,顶层模块只需要将线连到子模块中即可,所以是wire型也就顺理成章了
2、如果是多个子模块调用,子模块的中间输出也必须在顶层模块声明。(当然也是wire型)
    这个题就是一个例子,顶层模块调用了 三次子模块,且子模块之间是有联系的,这时顶层模块必须将中间输出也声明出来。
3、子模块的调用的语法结构如下:
    子模块名 (必须与子模块名完全相同)  顶层模块名(可以随便起)(
            .子模块变量1(必须与子模块中变量名完全相同)(顶层模块变量1),
            .子模块变量2(必须与子模块中变量名完全相同)(顶层模块变量2),
            ...
     );
    这个是子模块调用的结构。结构的讲解我这里不再赘述。如果读者看不懂,可以先查阅其他资料学习Verilog语法,不用急于做题。
顶层模块需要比较三个数的值,然后再输出最小的。如果我们编译的是c语言,我们很容易想到,只输出极值的比较题,只需要调用两次子模块就好了,第一次比较a和b,然后再将ab的最小值跟c去比即可。
但是,在Verilog中,这个思路是不行的。如果我们按照c语言的思路只用两次子模块,会输出错误的结果。问题在于时序,FPGA是并行执行的,如图所示:

在第一个上升沿,ab进入第一个比较器,c进入第二个比较器。但是比较器输出是需要时间的,在第一个上升沿,c立刻进入第二个比较器,但ab比较器的输出会较晚的进入第二个比较器,这就造成了输入时间不同步,从而造成输出错误。
解决办法也很简单,用三个比较器即可。

用三个比较器的目的是让输入子模块的时间都相等,这样就不会出现进入时间不同导致的错误。
所有代码如下:
`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] x,y;
     
zimokuai zimokuai_inst1(
    .clk(clk),
    .rst_n(rst_n),
    .a(a),
    .b(b),
     
    .d_reg(x)
);
     
zimokuai zimokuai_inst2(
    .clk(clk),
    .rst_n(rst_n),
    .a(a),
    .b(c),
     
    .d_reg(y)
); 
     
zimokuai zimokuai_inst3(
    .clk(clk),
    .rst_n(rst_n),
    .a(x),
    .b(y),
     
    .d_reg(d)
);     
endmodule
 
 
 
 
 
 
 
module zimokuai(
    input clk,
    input rst_n,
    input [7:0]a,
    input [7:0]b,
     
    output reg [7:0] d_reg
);
 
always@(posedge clk or negedge rst_n)
    if(rst_n == 1'b0)
        d_reg <= 8'd0;
    else if(a < b)
        d_reg <= a;
    else
        d_reg <= b;
 
endmodule