题解 | #使用子模块实现三输入数的大小比较#
使用子模块实现三输入数的大小比较
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
