思路:
法一:使用三个比较器完成
法二:使用两个比较器加一个触发器
解析:
module模块
一个.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的较小值,所以此时需要另加一个触发器进行延时一拍。 所以为了同步,否则要例化三次。