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。

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/magnolia666/p/16814993.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!