首页 > 试题广场 >

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

[编程题]使用子模块实现三输入数的大小比较
  • 热度指数:95500 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解


在数字芯片设计中,通常把完成特定功能且相对独立的代码编写成子模块,在需要的时候再在主模块中例化使用,以提高代码的可复用性和设计的层次性,方便后续的修改。

请编写一个子模块,将输入两个8bit位宽的变量data_a,data_b,并输出data_a,data_b之中较小的数。并在主模块中例化,实现输出三个8bit输入信号的最小值的功能。

子模块的信号接口图如下:


主模块的信号接口图如下:


使用Verilog HDL实现以上功能并编写testbench验证。



输入描述:
clk:系统时钟
rst_n:异步复位信号,低电平有效
a,b,c:8bit位宽的无符号数


输出描述:
d:8bit位宽的无符号数,表示a,b,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] w_m;
wire [7:0] w_n;
main_sub_compare main_sub_compare_inst0(
     .i_clk     ( clk   )
    ,.i_rst_n   ( rst_n )
    ,.i_a       ( a     )
    ,.i_b       ( b     )
    ,.o_c       ( w_m   )
);

main_sub_compare main_sub_compare_inst1(
     .i_clk     ( clk   )
    ,.i_rst_n   ( rst_n )
    ,.i_a       ( c     )
    ,.i_b       ( b     )
    ,.o_c       ( w_n   )
);

main_sub_compare main_sub_compare_inst2(
     .i_clk     ( clk   )
    ,.i_rst_n   ( rst_n )
    ,.i_a       ( w_m   )
    ,.i_b       ( w_n   )
    ,.o_c       ( d     )
);

endmodule

module main_sub_compare(
     input          i_clk
    ,input          i_rst_n
    ,input  [7:0]   i_a
    ,input  [7:0]   i_b

    ,output [7:0]   o_c
);

assign o_c = (i_a > i_b) ? i_b : i_a;   //我觉得去掉o_c的reg这样也可以 这题也许有歧义?

endmodule
发表于 2025-01-10 22:58:35 回复(0)
不能只例化两次模块,逻辑是正确的,但是忽略了时序问题,两个模块同时运行的,第一个模块还没必出结果第二个模块就开始运行了,需要打一拍解决时序问题
发表于 2024-09-01 16:43:21 回复(0)
有大佬可以解释一下为什么12,13行报错吗。我感觉我的语法没出现啥问题。
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]w1;
 compare_1(.clk(clk),.rst_n(rst_n),.a(a),.b(b),.c(w1));
 compare_2(.clk(clk),.rst_n(rst_n),.a(w1),.b(c),.c(d));

endmodule

module compare(
	input clk,
	input rst_n,
	input [7:0]a,
	input [7:0]b,
	output [7:0]c
);
always @(posedge clk&nbs***bsp;negedge rst_n)
begin 
	if(~rst_n)
	c=0;
	else 
	if (a<b)
	c=a;
	else
	c=b;
end
endmodule



编辑于 2024-02-29 17:33:17 回复(0)

`timescale 1ns/1ns
module sub_mod (
    input clk,
    input rst_n,
    input [7:0] a,
    input [7:0] b,
    output reg [7:0] c
);
    wire [8:0] less;
	wire [7:0] d;
	wire [7:0] e;
	generate
		genvar i;
		assign less[0] = 0;
		for(i=7;i>=0;i=i-1)begin
			// assign less[i+1]= (a[i]^b[i])?a[i]:less[i];
			assign e[i] = a[i]^b[i];
			assign less[i+1]= (e[i]&a[i])|((~e[i])&less[i]);
			assign d[i] = (less[8]&b[i])|((~less[8])&a[i]);
		end

	endgenerate
	

    always@(posedge clk&nbs***bsp;negedge rst_n) begin
        if(!rst_n)
            c <= 8'b0;
        else 
            c <= d;
    end
     

endmodule
module main_mod(
	input clk,
	input rst_n,
	input [7:0]a,
	input [7:0]b,
	input [7:0]c,
	
	output wire [7:0]d
);


    wire [7:0] min_ab;
    wire [7:0] min_ac;
    wire [7:0] min_abc;
     
    sub_mod sub_mod_U0(
        .clk      (clk),
        .rst_n    (rst_n),
        .a        (a),
        .b        (b),
        .c        (min_ab)
    );
     
    sub_mod sub_mod_U1(
        .clk      (clk),
        .rst_n    (rst_n),
        .a        (a),
        .b        (c),
        .c        (min_ac)
    );
 
    sub_mod sub_mod_U2(
        .clk      (clk),
        .rst_n    (rst_n),
        .a        (min_ab),
        .b        (min_ac),
        .c        (min_abc)
    );
 
    assign d = min_abc;
endmodule

发表于 2023-08-05 00:20:34 回复(0)
`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]temp,temp1;
min2 u1(clk,rst_n,a,b,temp);
min2 u2(clk,rst_n,b,c,temp1);
min2 u3(clk,rst_n,temp,temp1,d);

endmodule

module min2(
	input clk,
	input rst_n,
	input [7:0]a,
	input [7:0]b,

	output reg [7:0]d
);

always@(posedge clk&nbs***bsp;negedge rst_n)begin
	if(!rst_n) d <= 8'd0;
	else if(a<=b) d<=a;
	else d<=b;
end
endmodule

发表于 2023-07-27 17:34:25 回复(0)
为什么不能只例化一个子模块,a和b比完得到n,n在和c比较得到d?这样只需要一个例化一个。我这个代码写出来为啥会得到一个a b 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 reg [7:0]d
);

	wire [7:0] c_temp;

	sub_mod u_sub_mod(

		.clk (clk),
		.rst_n (rst_n),
		.data_a (a),
		.data_b (b),
		
		.data_c (c_temp)


	);


	always@(posedge clk&nbs***bsp;negedge rst_n)begin
		if(~rst_n)begin
			d <= 8'b0;
		end
		else begin
			if(c_temp > c)begin
				d <= c;
			end
			else begin
				d <= c_temp;
			end
		end
	end


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&nbs***bsp;negedge rst_n)begin
		if(~rst_n)begin
			data_c <= 8'b0;
		end
		else begin
			if(data_a > data_b)begin
				data_c <= data_b;
			end
			else begin
				data_c <= data_a;
			end
		end
	end

endmodule

发表于 2023-05-11 22:25:44 回复(0)
一开始是打算例化两个子模块,写出来后发现时序不对,发现如果使用两个子模块的话,由于子模块之间是并行运行的,那么会导致后一个模块的c不会和当前周期的min(a,b)比较,只和前一个周期比较,那么只需要再增加一个模块,第一个模块比较(a,b),第二个模块比较(a,c),第三个模块比较min(a,b)和min(a,c)
发表于 2022-09-13 19:46:59 回复(0)
`timescale 1ns/1ns

module min(
    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 <= 0;
        else c_r <= a > b ? b : a;
    end
    assign c = c_r;
endmodule

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] ab_min;
    reg [7:0] c_r;
    
    always@(posedge clk) begin
        c_r <= c;
    end
    
    min min_inst_0(
        .clk(clk),
        .rst_n(rst_n),
        .a(a),
        .b(b),
        .c(ab_min)
    );
    
    min min_inst_1(
        .clk(clk),
        .rst_n(rst_n),
        .a(ab_min),
        .b(c_r),
        .c(d)
    );
    
endmodule
发表于 2022-08-14 16:35:03 回复(0)
module main_mod(
    input clk,
    input rst_n,
    input [7:0]a,
    input [7:0]b,
    input [7:0]c,
    
    output [7:0]d
);
   
 
    task comp_2 ;
        input [7:0] a;
        input [7:0] b;
        output [7:0] c;
        
        assign c = (a-b>0)?b:a;
  
    assign d =  comp_2(comp_2(a,b),   comp_2(a,c));
endmodule
发表于 2022-07-14 12:53:08 回复(0)
易错点:该电路为时序逻辑,先选择a、b最小的输出m,然后再将m与c比较输出d,因此需要2拍延迟。如果a、b最小值m直接与c进行比较,则时序错误,c永远比较的都是m的前一拍的值,故需要将c打一拍即可,完成时序对其。

个人觉得这跟综合是否会复制电路没关系,verilog执行每个子module都是并行的,理解输入、输出的时序关系就很好理解了
发表于 2022-05-30 11:41:48 回复(0)
采用时序逻辑例化两次子模块时,第一个例化的最小值经过一个时钟周期才能得到,此时若再拿去与第三个数比较大小进行第二次例化时,第三个数已经不是上个周期的数了,解决办法就是将第三个数缓存一个周期,再进行第二次例化子模块,结果可以通过测试。
`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] c_out1;
    slave_mod s1(
        .clk(clk),
        .rst_n(rst_n),
        .a(a),
        .b(b),
        .c_out(c_out1)
    );
 
    reg [7:0] c1;
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n)
            c1 <= 8'b0;
        else
            c1 <= c;
    end

        slave_mod s2(
        .clk(clk),
        .rst_n(rst_n),
        .a(c_out1),
        .b(c1),
        .c_out(d)
    );   
           
endmodule

module slave_mod(
    input clk,
    input rst_n,
    input [7:0]a,
    input [7:0]b,
    output [7:0] c_out
);
    reg [7:0] c_out;
    always @(posedge clk,negedge rst_n) begin
        if(!rst_n)
            c_out <= 8'b0;
        else
            if(a>b)
                c_out <= b;
            else
                c_out <= a;
    end
            
endmodule

发表于 2022-04-21 18:12:45 回复(5)
当a,b,c输入的时钟刚好在一个时钟周期并且是上升沿的时候,例化两次和三次结果一样都是延时一个周期输出
发表于 2022-03-27 17:49:59 回复(0)
比较器直接构造纯组合逻辑,a、b比较的结果与c比较,比较结果在时钟上升沿所存到FF;
两个比较器就可以了,单时钟周期完成,因此输出结果较testbench提前一个时钟周期
发表于 2022-03-05 12:24:06 回复(9)

问题信息

难度:
15条回答 1017浏览

热门推荐

通过挑战的用户

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