verilog more features 代码总结汇总

1.简易条件选择语句

格式为:(condition ?  a : b)对了选a不对选b

题目:Conditional

Given four unsigned numbers, find the minimum. Unsigned numbers can be compared with standard comparison operators (a < b). Use the conditional operator to make two-way min circuits, then compose a few of them to create a 4-way min circuit. You'll probably want some wire vectors for the intermediate results.

答案:

 1 module top_module (
 2     input [7:0] a, b, c, d,
 3     output [7:0] min);//
 4     wire [7:0] buffer1,buffer2;
 5     // assign intermediate_result1 = compare? true: false;
 6     assign buffer1 = (a<b? a:b);
 7     assign buffer2 = (c<d? c:d);
 8     
 9     assign min = (buffer1<buffer2? buffer1:buffer2);
10 
11 endmodule

 

2.简化多个同一寄存器间的位操作

从下面的例子可以简单易懂的了解本部分的含义

& a[3:0]     // AND: a[3]&a[2]&a[1]&a[0]. Equivalent to (a[3:0] == 4'hf)
| b[3:0]     // OR:  b[3]|b[2]|b[1]|b[0]. Equivalent to (b[3:0] != 4'h0)
^ c[2:0]     // XOR: c[2]^c[1]^c[0]

当然该方法不只局限于以上三种符号像是~&这样的符号也可以套用这种方法。

题目:

Parity checking is often used as a simple method of detecting errors when transmitting data through an imperfect channel. Create a circuit that will compute a parity bit for a 8-bit byte (which will add a 9th bit to the byte). We will use "even" parity, where the parity bit is just the XOR of all 8 data bits.

答案:

1 module top_module (
2     input [7:0] in,
3     output parity); 
4     
5     assign parity = ^in[7:0];
6 
7 endmodule

这道题有点过于简单了。。

 

3.熟练使用上面的方法

题目:Gates100

Build a combinational circuit with 100 inputs, in[99:0].

There are 3 outputs:

  • out_and: output of a 100-input AND gate.
  • out_or: output of a 100-input OR gate.
  • out_xor: output of a 100-input XOR gate.

答案:

 1 module top_module( 
 2     input [99:0] in,
 3     output out_and,
 4     output out_or,
 5     output out_xor 
 6 );
 7     assign out_and = &in[99:0];
 8     assign out_or = |in[99:0];
 9     assign out_xor = ^in[99:0];
10 
11 endmodule

 

4.verilog中的for循环

其具体用法与C语言十分相似,但是for循环对应于硬件电路的意义暂时没有搞懂,只好浅尝辄止。

题目:Vector100r

Given a 100-bit input vector [99:0], reverse its bit ordering.

答案:

 1 module top_module( 
 2     input [99:0] in,
 3     output [99:0] out
 4 );
 5     int i = 0;
 6     always @(*) begin
 7         for(i = 0;i < 100;i++)
 8             out[100-i-1] = in[i];
 9     end
10 
11 endmodule

 

5.for循环熟练使用

题目:

A "population count" circuit counts the number of '1's in an input vector. Build a population count circuit for a 255-bit input vector.

答案:

 1 module top_module( 
 2     input [254:0] in,
 3     output [7:0] out );
 4     int i;
 5     always @(*) begin
 6         out = 8'h00;
 7         for(i = 0 ; i<255 ; i++ )
 8             begin
 9                 if(in[i] == 1)
10                     out = out+1'b1;
11                 else
12                     out = out+1'b0;
13             end
14     end
15 
16 endmodule

做这道题的时候有两个点卡了我很久:

一是不确定verilog有没有加的操作,后来经过查阅后发现是可以直接使用+的。

二是忘记初始化out端口,导致无法输出正常结果,加上out = 8'h00即可。

 

6.verilog中的generate语句使用方法

generate语法:

  • 定义genvar,作为generate种的循环变量。
  • generate语句中定义的for语句,必须要有begin,为后续增加标签做准备。
  • begin必须要有名称,也就是必须要有标签,因为标签会作为generate循环的实例名称。
  • 可以使用在generate语句中的类型主要有:
    • ü  module(模块)
    • ü  UDP(用户自定义原语)
    • ü  门级原语
    • ü  连续赋值语句
    • ü  initial或always语句
  • 基本结构如下:

genvar 循环变量名;

generate

    // generate循环语句

    // generate 条件语句

    // generate 分支语句

    // 嵌套的generate语句

endgenerate

下面是generate的三个例子:

一、generate-loop循环语句

 

二、generate-conditional条件语句

generate允许对语句进行条件选择,即将条件选择加入到generate中的for循环中,只例化条件成立时对应的语句或者module。

 

三、generate-case分支语句

generate-case分支语句与generate-条件语句类似,只不过将原来的分支语句换做了case语句。

 

 

有了上面的语法基础后,可以开始尝试做本题了:

题目:Adder100i

Create a 100-bit binary ripple-carry adder by instantiating 100 full adders. The adder adds two 100-bit numbers and a carry-in to produce a 100-bit sum and carry out. To encourage you to actually instantiate full adders, also output the carry-out from each full adder in the ripple-carry adder. cout[99] is the final carry-out from the last full adder, and is the carry-out you usually see.

答案:

 1 module top_module( 
 2     input [99:0] a, b,
 3     input cin,
 4     output [99:0] cout,
 5     output [99:0] sum );
 6     
 7     assign cout[0] = a[0]&b[0]|a[0]&cin|b[0]&cin;
 8     assign sum[0] = a[0]^b[0]^cin;
 9     
10     genvar i ;
11     generate
12         for(i = 1;i<100;i++)
13             begin:adder99
14                 assign cout[i] = a[i]&b[i]|a[i]&cout[i-1]|b[i]&cout[i-1];
15                 assign sum[i] = a[i]^b[i]^cout[i-1];    
16             end
17     endgenerate
18 
19 endmodule

这份代码是我参考了网上其他兄弟的结果...其实这道题不用generate而用always也能实现,因为没有实例化任何模块。

 

7.进一步熟悉使用generate语句

本部分切实使用并提供到了BCD加法器,这里肯定要用generate实现本题目。

题目:Bcdadd100

You are provided with a BCD one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out.

答案:

 1 module top_module( 
 2     input [399:0] a, b,
 3     input cin,
 4     output cout,
 5     output [399:0] sum );
 6     
 7     genvar i ;
 8     reg [100:0]buffer;
 9     assign buffer[0] = cin;
10     
11     generate
12         for(i = 1;i<=100;i++)
13             begin:lable
14                 bcd_fadd adder(.a(a[(i*4-1)-:4]),
15                                .b(b[(i*4-1)-:4]),
16                                   .cin(buffer[i-1]),
17                                .cout(buffer[i]),
18                                .sum(sum[(i*4-1)-:4]));
19             end
20     endgenerate
21     assign cout = buffer[100];
22     
23 endmodule

这道题值得分析一下,由于verilog中实现的电路为并发性的,所以不能单纯的使用上一个加法器的cout送入洗一个加法器的cin,故考虑使用一个缓冲数组来实现所有加法器的进位识别。

为什么要创建101位地数组?因为首位可以用来存放模块外送入的进位,这样就免得单独对首个加法器进行初始化了。

最后注意在generate部分代码后要对整个模块的cout幅值。

同时注意[(i*4-1)-:4]这部分代码,表示从(i*4-1)开始向下四位。

这样的用法还有:

1 big_vect    [0  +:   8]  从0 开始,升序,位宽为8     ======》》》》》big_vect   [7 :0]
2 little_vect  [0  +:   8]  从0 开始,升序,位宽为8     ======》》》》》little_vect  [0 :7]
3 big_vect   [15 -:   8]  从15开始,降序,位宽为8    ======》》》》》big_vect    [15 :8] 
4 little_vect [15 -:   8]  从15开始,降序,位宽为8    ======》》》》》little_vect   [8:15]

 

posted @ 2021-11-19 23:09  super_gotta  阅读(236)  评论(0)    收藏  举报