【HDLBits刷题笔记】03 Modules: Hierachy
Module
模块例化的两种方式:按端口位置例化、按端口名例化。
module top_module ( input a, input b, output out ); mod_a instance1 ( .in1(a), .in2(b), .out(out) ); endmodule
Module pos
按端口顺序例化。
module top_module ( input a, input b, input c, input d, output out1, output out2 ); mod_a inst(out1, out2, a, b, c, d); endmodule
Module name
按端口名例化
module top_module ( input a, input b, input c, input d, output out1, output out2 ); mod_a inst (.out1(out1), .out2(out2), .in1(a), .in2(b), .in3(c), .in4(d)); endmodule
Module shift
例化三个寄存器实现一个移位寄存器。
module top_module ( input clk, input d, output q ); wire q1,q2; my_dff dff1 ( .clk(clk), .d(d), .q(q1) ); my_dff dff2 ( .clk(clk), .d(q1), .q(q2) ); my_dff dff3 ( .clk(clk), .d(q2), .q(q) ); endmodule
Module shift8
八位的移位寄存器,使用了一个sel信号选通输出,标准答案用的都是按端口顺序例化,看起来会简洁一些,但是不利于大型工程的维护和可阅读性。
module top_module ( input clk, input [7:0] d, input [1:0] sel, output [7:0] q ); wire [7:0]q1; wire [7:0]q2; wire [7:0]q3; my_dff8 dff1 ( .clk(clk), .d(d), .q(q1) ); my_dff8 dff2 ( .clk(clk), .d(q1), .q(q2) ); my_dff8 dff3 ( .clk(clk), .d(q2), .q(q3) ); always@(*) begin case(sel) 0:q=d; 1:q=q1; 2:q=q2; 3:q=q3; endcase end endmodule
Module add
题目要求使用两个16位的加法器实现一个32位的加法器。
module top_module( input [31:0] a, input [31:0] b, output [31:0] sum ); wire cout; add16 adder1( a[15:0], b[15:0], 1'b0, sum[15:0], cout ); add16 adder2( a[31:16], b[31:16], cout, sum[31:16], ); endmodule
Module fadd
相比上一题多了一个一位的加法器模块,16位加法器仍然提供。答案这里使用了全加器的逻辑表达式:sum = a ^ b ^ cin
,cout = a&b | a&cin | b&cin,我这里是取巧直接用了一个加法符号。
module top_module ( input [31:0] a, input [31:0] b, output [31:0] sum );// wire cout; add16 adder1( a[15:0], b[15:0], 1'b0, sum[15:0], cout ); add16 adder2( a[31:16], b[31:16], cout, sum[31:16], ); endmodule module add1 ( input a, input b, input cin, output sum, output cout ); // Full adder module here assign {cout,sum}=a+b+cin; endmodule
Module cseladd
前面用的行波进位(ripple carry)加法器有一个缺点:必须要等低位的计算结束后才能计算高位,这道题高位使用了两个加法器,一个假设进位是0一个假设仅为是1,待低位完成计算后,只需要选通相应的数据通路即可。
module top_module( input [31:0] a, input [31:0] b, output [31:0] sum ); wire cout; wire [15:0] sum_temp1; wire [15:0] sum_temp2; add16 adder1( a[15:0], b[15:0], 1'b0, sum[15:0], cout ); add16 adder2( a[31:16], b[31:16], 0, sum_temp1, ); add16 adder3( a[31:16], b[31:16], 1, sum_temp2, ); assign sum[31:16] = cout?sum_temp2:sum_temp1; endmodule
Module addsub
加减器,减法通过将b取补码实现,这里直接将b与repeat之后的sub进行异或运算,实现了减法时将b取反。同时将低位的16位加法器的cin输入sub,可以实现负数时的补码运算,比较巧妙。
module top_module( input [31:0] a, input [31:0] b, input sub, output [31:0] sum ); wire cout; wire [31:0]b1; assign b1=b^{32{sub}}; add16 adder1( a[15:0], b1[15:0], sub, sum[15:0], cout ); add16 adder2( a[31:16], b1[31:16], cout, sum[31:16], ); endmodule
最后一道题还想了挺久,但是其实题目中和图中已经告诉了sub连cin。