思路:
法一:使用三个比较器完成
法二:使用两个比较器加一个触发器
解析:
一个.v文件中可以写多个模块module(一般是一个文件写一个module),其中主模块的名字和.v文件名相同。且要注意子模块和主模块都要有endmodule,不然会报错,且最好先写主模块,再写子模块。子模块也要像主模块格式那样写。
- module模块名(
-
- 端口描述
-
- );
-
- ...
-
- endmodule
例化
- 模块名例化名(
-
- 端口参数传递(按位置或者按名字均可)
-
- );
比如模块名是“人”,例化名可以起名为“张三”、“李四”,这样就例化了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比较!
解法一
- `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)
- );
- //先得到bc之中的较小值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)
- begin
- if(!rst_n)
- data_c <= 8'b0;
- else if(data_a < data_b)
- data_c <= data_a;
- else
- data_c <= data_b;
- end
- endmodule
解法二:通过延时输入信号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
- );
- reg [7:0] c_0;
- wire [7:0] tmp0;
- always@(posedge clk or negedge rst_n)begin
- if(!rst_n)
- c_0 <= 0;
- else
- c_0 <= c;
- end
- sub_mod sub_mod0(.clk(clk), .rst_n(rst_n), .a(a), .b(b), .c(tmp0));
- sub_mod sub_mod1(.clk(clk), .rst_n(rst_n), .a(tmp0), .b(c_0), .c(d));
- endmodule
-
- module sub_mod(
- input clk,
- input rst_n,
- input [7:0] a,
- input [7:0] b,
-
- output [7:0] c
- );
- reg [7:0] c_r;
- always@(posedge clk or negedge rst_n) begin
- if(~rst_n)
- c_r <= 8'b0;
- else
- c_r <= a < b? a:b;
- end
- assign c = c_r;
- endmodule
这一题不能为了简化资源而只例化两次子模块sub_mod,因为是always块里的非阻塞赋值,比较的结果会差一拍。 如果非要只例化两次,比如说先比较a与b,然后直接把较小的结果与c比较的话,那么得到的结果就是min(a,b)与下一时刻的c的较小值,所以此时需要另加一个触发器进行延时一拍。 所以为了同步,否则要例化三次。