题解 | #使用子模块实现三输入数的大小比较#
使用子模块实现三输入数的大小比较
http://www.nowcoder.com/practice/bfc9e2f37fe84c678f6fd04dbce0ad27
目录
代码
本次代码使用了三个比较器完成。此外,还有一种解法放在了简析中。
sub_mod0
:比较器0,a
和b
比较得到较小的值tmp0
;
sub_mod1
:比较器1,a
和c
比较得到较小的值tmp1
;
sub_mod2
:比较器2,tmp0
和tmp1
比较得到最小的值d
。
`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] tmp0, tmp1;
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(a), .b(c), .c(tmp1));
sub_mod sub_mod2(.clk(clk), .rst_n(rst_n), .a(tmp0), .b(tmp1), .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
简析
如下,一种典型的错误思路是使用两个比较器。
wire [7:0] tmp0,;
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), .c(d) );
由于比较器是时序逻辑,需要一个时钟周期才能得到结果,所以可能存在a
和b
比较结束时c
已经更新的情况。可以对c
打一拍,也就是在c
的路径上插入一个触发器,解决这个问题。代码如下:
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));
触发器的输出c_0
与比较结果tmp0
是同步的,不会因为c
的更新产生错误结果。同样可以类推,如果是组合逻辑实现的比较器,那就不需要插入触发器;如果是消耗N个时钟周期的比较器,那就插入N个触发器。在本题中,两个比较器加一个触发器的方法综合出来的电路逻辑门数应该少于三比较器的方法。
Verilog篇题解 文章被收录于专栏
本人对牛客网verilog篇题目一些理解