基于SparkRoad的Hdlbits学习(2)

代码学习:


Modules
此sub-module的声明方式需要掌握。下面的两段话很重要:

The hierarchy of modules is created by instantiating one module inside another, as long as all of the modules used belong to the same project (so the compiler knows where to find the module). The code for one module is not written inside another module's body (Code for different modules are not nested).

You may connect signals to the module by port name or port position. For extra practice, try both methods.
Connecting Signals to Module Ports
There are two commonly-used methods to connect a wire to a port: by position or by name.

By position
The syntax to connect wires to ports by position should be familiar, as it uses a C-like syntax. When instantiating a module, ports are connected left to right according to the module's declaration. For example:

mod_a instance1 ( wa, wb, wc );

This instantiates a module of type and gives it an instance name of "instance1", then connects signal (outside the new module) to the first port () of the new module, to the second port (), and to the third port (). One drawback of this syntax is that if the module's port list changes, all instantiations of the module will also need to be found and changed to match the new module. mod_awain1wbin2wcout

By name
Connecting signals to a module's ports by name allows wires to remain correctly connected even if the port list changes. This syntax is more verbose, however.

mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );

The above line instantiates a module of type named "instance2", then connects signal (outside the module) to the port named , to the port named , and to the port named . Notice how the ordering of ports is irrelevant here because the connection will be made to the correct name, regardless of its position in the sub-module's port list. Also notice the period immediately preceding the port name in this syntax.mod_awain1wbin2wcout
**模块调用两种方式:按位置调(简洁但不稳,顺序不可乱),按名称调(繁琐但很稳,顺序可变)**

完成代码如下:

module top_module ( input a, input b, output out );
    mod_a(.in1(a),.in2(b),.out(out));
endmodule

Connecting ports by position
这样的解答前提是题干中提供了module的定义顺序,且按照位置定义,直接得出。

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a(out1,out2,a,b,c,d);
endmodule

Connecting ports by name
继续的按照名称定义,同理完成。

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a(.out1(out1),.out2(out2),.in1(a),.in2(b),.in3(c),.in4(d));
endmodule

Three modules

module top_module ( input clk, input d, output q );
    wire t1;
    wire t2;
    my_dff dff1(clk,d,t1);   //按位置定义
    my_dff dff2(clk,t1,t2);
    my_dff dff3(clk,t2,q);
endmodule
/*
module top_module ( input clk, input d, output q );
    wire t1;
    wire t2;
    my_dff dff1(.clk(clk),.d(d),.q(t1));   //按名称定义,在对子模块的调用中要注意,不是用.input或.in1,而是.clk和.d和.q
    my_dff dff2(.clk(clk),.d(t1),.q(t2));
    my_dff dff3(.clk(clk),.d(t2),.q(q));
    
endmodule
*/

这个见夏宇闻老师《Verilog数字系统设计·第三版》P22的说明即可,一个是上层模块(top_module),一个是子模块(my_dff),然后借用子模块定义了三个实例部件:dff1,dff2,dff3,而在实例模块的定义中,使用按位置和按名称的定义都是可以的。


Modules and vectors

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;   //wire [7:0] q1,q2,q3;
    my_dff8 instance0 (clk,d,q1);
    my_dff8 instance1 (clk,q1,q2);
    my_dff8 instance2 (clk,q2,q3);
    always @(*)
        begin
            case(sel)
                2'b00:q = d;
                2'b01:q = q1;
                2'b10:q = q2;
                2'b11:q = q3;
            endcase
        end

endmodule

Adder1
之前自己的代码报错,经检查发现是在输入()时,用的是中文输入。网上的代码我觉得并不足够好,因为在前面的题目中已经明确了这种题型只要用位置命名即可,不需要用名字命名。以下的三种代码均成立。

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    /*wire t1;   //有些臃肿
    wire t2;
    wire cin;
    assign cin=1'b0;
    add16 instance1(.a(a[15:0]),.b(b[15:0]),.cin(cin),.sum(sum[15:0]),.cout(t1));
    add16 instance2(a[31:16],b[31:16],t1,sum[31:16],t2);*/
    /*wire cin;
    wire [15:0] sum1,sum2;   //此为网上的代码
    wire cout1,cout2;
    assign cin = 1'b0;
    add16 instance1(.a(a[15:0]),.b(b[15:0]),.cin(cin),.sum(sum1),.cout(cout1));
    add16 instance2(.a(a[31:16]),.b(b[31:16]),.cin(cout1),.sum(sum2),.cout(cout2));
    assign sum = {sum2,sum1};*/
    wire t1;
    wire t2;
    add16 instance1(a[15:0],b[15:0],1'b0,sum[15:0],t1);
    add16 instance2(a[31:16],b[31:16],t1,sum[31:16],t2);

endmodule

Adder2

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire cin;
    wire cout1;
    wire cout2;
    wire [15:0] sum1,sum2;
    assign cin = 1'b0;
    add16 instance0 (a[15:0],b[15:0],cin,sum1,cout1);
    add16 instance1 (a[31:16],b[31:16],cout1,sum2,cout2);
    assign sum = {sum2,sum1};
    
endmodule
	
module add1 ( input a, input b, input cin,   output sum, output cout );   //等于是小模块的重新定义
    //因为这是add instance0中的16个add1的定义
	assign sum = a^b^cin;
    assign cout = a&b | a&cin | b&cin;
// Full adder module here

endmodule
/*
module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire cin;
    wire cout1;
    wire cout2;
    wire [15:0] sum1,sum2;
    assign cin = 1'b0;
    add16 instance0 (.a(a[15:0]),.b(b[15:0]),.cin(cin),.sum(sum1),.cout(cout1));
    add16 instance1 (.a(a[31:16]),.b(b[31:16]),.cin(cout1),.sum(sum2),.cout(cout2));
    assign sum = {sum2,sum1};
    
endmodule
	
module add1 ( input a, input b, input cin, output sum, output cout );
	assign sum = a^b^cin;
    assign cout = a&b | a&cin | b&cin;
// Full adder module here

endmodule
*/

等于是先定义了上层模块,并且完成了sum的定义,再在子模块中定义了add1的模块,因为在上层定义中调用了add16。


Carry-select adder

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
	wire cin1,cin2,cin3,cout1,cout2,cout3;
    wire [15:0] sum1,sum2,sum3;
    assign cin1 = 1'b0;
    assign cin2 = 1'b0;
    assign cin3 = 1'b1;
    add16 add1 (a[15:0],b[15:0],cin1,sum1,cout1);
    add16 add2 (a[31:16],b[31:16],cin2,sum2,cout2);
    add16 add3 (a[31:16],b[31:16],cin3,sum3,cout3);
    
    always@(*)
        begin
        	case(cout1)
                1'b0:sum={sum2,sum1};
                1'b1:sum={sum3,sum1};
            endcase
        end

endmodule
/*
module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
	wire cin1,cin2,cin3,cout1,cout2,cout3;
    wire [15:0] sum1,sum2,sum3;
    assign cin1 = 1'b0;
    assign cin2 = 1'b0;
    assign cin3 = 1'b1;
    add16 add1 (.a(a[15:0]),.b(b[15:0]),.cin(cin1),.sum(sum1),.cout(cout1));
    add16 add2 (.a(a[31:16]),.b(b[31:16]),.cin(cin2),.sum(sum2),.cout(cout2));
    add16 add3 (.a(a[31:16]),.b(b[31:16]),.cin(cin3),.sum(sum3),.cout(cout3));
    
    always@(*)
        begin
        	case(cout1)
                1'b0:sum={sum2,sum1};
                1'b1:sum={sum3,sum1};
            endcase
        end

endmodule
*/

在Hdlbits中基本上子模块都不需要自己再去定义了,直接调用即可。


Adder-subtractor

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
	wire cin;
    wire cout1,cout2;
    wire [15:0]sum1,sum2;
    wire [31:0] b_n;
    assign b_n = b ^ {32{sub}};
    
    add16 add1 (a[15:0],b_n[15:0],sub,sum1,cout1);
    add16 add2 (a[31:16],b_n[31:16],cout1,sum2,cout2);
    
    assign sum = {sum2,sum1};

/*module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire cin;
    wire cout1,cout2;
    wire [15:0]sum1,sum2;
    wire [31:0] b_n;
    assign b_n = b ^ {32{sub}};
    
    add16 add1 (.a(a[15:0]),.b(b_n[15:0]),.cin(sub),.sum(sum1),.cout(cout1));
    add16 add2 (.a(a[31:16]),.b(b_n[31:16]),.cin(cout1),.sum(sum2),.cout(cout2));
    
    assign sum = {sum2,sum1};

endmodule
*/
endmodule

总结:

结合夏宇闻老师《Verilog数字系统设计·第三版》2.1部分,理解了上层模块与子模块的使用之后,这部分的题目基本上可以解决了。

posted @ 2023-05-22 17:08  江左子固  阅读(10)  评论(0编辑  收藏  举报