题解 | #使用子模块实现三输入数的大小比较#

使用子模块实现三输入数的大小比较

http://www.nowcoder.com/practice/bfc9e2f37fe84c678f6fd04dbce0ad27

目录

代码

本次代码使用了三个比较器完成。此外,还有一种解法放在了简析中。
alt

sub_mod0:比较器0,ab比较得到较小的值tmp0
sub_mod1:比较器1,ac比较得到较小的值tmp1
sub_mod2:比较器2,tmp0tmp1比较得到最小的值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

简析

如下,一种典型的错误思路是使用两个比较器。
alt

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)   );

由于比较器是时序逻辑,需要一个时钟周期才能得到结果,所以可能存在ab比较结束时c已经更新的情况。可以对c打一拍,也就是在c的路径上插入一个触发器,解决这个问题。代码如下:
alt

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篇题目一些理解

全部评论
感谢解惑
点赞 回复 分享
发布于 02-21 10:15 湖南

相关推荐

94 3 评论
分享
牛客网
牛客企业服务