题解 | #使用子模块实现三输入数的大小比较#
使用子模块实现三输入数的大小比较
https://www.nowcoder.com/practice/bfc9e2f37fe84c678f6fd04dbce0ad27
本来也准备直接例化两次;看完揭发后发现不行,还是需要例化三次。参考解法和讨论,做下记录防止自己汪
参考解法:
1.子模块写成组合逻辑,一个周期就可以比较完。比答案早一个周期,要对的话要打一拍。
2,子模块也带时序,用两个模块先比较a和b,a和c。再用一个模块比较它两的结果,跟答案一样。
3,子模块也带时序,一个模块比较a和b得到d1;将c打一拍,再用一个模块比较d2和c,在d1出现的下一个周期得到结果。先选择a、b最小的输出m,然后再将m与c比较输出d,因此需要2拍延迟。如果a、b最小值m直接与c进行比较,则时序错误,c永远比较的都是m的前一拍的值,故需要将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] min_ab,min_ac; son_mod min1( .clk(clk), .rst_n(rst_n), .data_a(a), .data_b(b), .data_c(min_ab) ); son_mod min2( .clk(clk), .rst_n(rst_n), .data_a(a), .data_b(c), .data_c(min_ac) ); son_mod min3( .clk(clk), .rst_n(rst_n), .data_a(min_ab), .data_b(min_ac), .data_c(d) ); endmodule module son_mod( input clk, input rst_n, input [7:0] data_a, input [7:0] data_b, output [7:0] data_c ); reg[7:0] c_r; always@(posedge clk or negedge rst_n)begin if (!rst_n) c_r <= 0; else if (data_a < data_b) c_r <= data_a; else c_r <= data_b; end assign data_c = c_r; endmodule
testbench
testbench中module test();要改成module testbench();
`timescale 1ns/1ns module testbench(); reg signed [7:0] a,b,c; reg clk,rst_n; wire [7:0]d; initial begin $dumpfile("out.vcd"); $dumpvars(0,testbench); end //always #5 clk = !clk; initial begin clk = 1; repeat(50) #1 clk = ~clk; end initial begin rst_n = 0; #2;rst_n = 1; end main_mod dut( .clk(clk), .rst_n(rst_n), .a(a), .b(b), .c(c), .d(d) ); initial begin #2; a = 1; b = 2; c = 3; #10; a = 6; b = 5; c = 4; #10; a = 9; b = 7; c = 8; #20 $stop; end endmodule
看图形可以看出来比较会有延时。
看讨论大神讲的有道理,没看懂。先做个标记以后看。(实际上例化2个子模块也可以,比较器里也可以用组合逻辑写。。这个没看懂)
tb里想的是比较器用时序逻辑写,例化3个子模块,这样需要2个周期计算出结果
实际上例化2个子模块也可以,比较器里也可以用组合逻辑写
如果比较器里用组合逻辑写,例化2个或者3个子模块都可以,这样子当前周期就可以直接计算出结果,那么做完之后将输出结果打2拍就和tb结果一致了
如果比较器里用时序逻辑写,例化3个子模块,是和tb一致
如果比较器里用时序逻辑写,例化2个子模块,其中第一个子模块输入a、b,第二个子模块输入ab的最小值和c_1d,这样需要1个周期计算出结果,所以将结果打1拍就可以和tb结果一致
用组合逻辑+2个子模块的代码:(我不知道这个为什么是组合逻辑。。看来我自己写的就是组合逻辑。那么时序逻辑得代码又是什么样子?)
wire [7:0] min_a_b; gen_min Inst_a_b ( .clk (clk), .rst_n (rst_n), .a (a), .b (b), .c (min_a_b) ); wire [7:0] min_a_b_c; gen_min Inst_a_b_c ( .clk (clk), .rst_n (rst_n), .a (min_a_b), .b (c), .c (min_a_b_c) ); reg [7:0] min_abc_1d; reg [7:0] min_abc_2d; always @ (posedge clk&nbs***bsp;negedge rst_n) begin if (~rst_n) begin min_abc_1d <= 'd0; min_abc_2d <= 'd0; end else begin min_abc_1d <= min_a_b_c; min_abc_2d <= min_abc_1d; end end assign d = min_abc_2d; endmodule