基础数字电路的Verilog写法

  Verilog是硬件描述电路,我对此一直稀里糊涂,于是将锆石科技开发板附带的的一些基础数字电路Verilog程序整理记录下来,并且查看他们的RTL视图,总算有点理解了。

  1.基本运算符

 1 module Example_Operation
 2 ( 
 3     input  [3:0]         a       ,
 4     input  [3:0]         b       ,
 5     input  [3:0]        c       ,
 6     
 7     output [3:0]        c1      ,
 8     output [3:0]        c2      ,
 9     output [5:0]        c3      ,
10     output [3:0]        c4      ,
11     output [3:0]        c5      ,
12     output [3:0]        d1      ,
13     output [3:0]        d2      ,
14     output [3:0]        d3      ,
15     output [3:0]        d4      ,
16     output [3:0]        e1      ,
17     output [3:0]        e2      ,
18     output [3:0]        e3      ,
19     output [3:0]        f1      ,
20     output [3:0]        f2      ,
21     output [3:0]        d11     ,
22     output [3:0]        c11     ,
23     output [3:0]        c22     ,
24     output [3:0]        c33     ,
25     output [3:0]        c44     ,
26     output [3:0]        c55     ,
27     output [3:0]        c66     ,
28     output [3:0]        e11     ,
29     output [3:0]        e22     ,
30     output [7:0]        f11     ,
31     output [7:0]        f22
32 );
33 
34 //== waveform1 算数运算符
35 //======================================================================
36 assign c1 = a + b;      //
37 assign c2 = a - b;      //
38 assign c3 = a * b;      //
39 assign c4 = a / b;      //
40 assign c5 = a % b;      //求余
41 
42 //== waveform2 关系运算符
43 //======================================================================
44 assign d1 = a >  b;     //大于
45 assign d2 = a <  b;     //小于
46 assign d3 = a >= b;     //大于等于
47 assign d4 = a <= b;     //小于等于
48 
49 //== waveform3 逻辑运算符
50 //======================================================================
51 assign e1 = !a;         //
52 assign e2 = a && b;     //
53 assign e3 = a || b;     //54 
55 //== waveform4 逻辑等式运算符
56 //======================================================================
57 assign f1 = a == b;     //判断相等
58 assign f2 = a != b;     //判断不等
59 
60 //== waveform5 三目条件运算符
61 //======================================================================
62 assign d11 = a ? b : c; //a为真,则d11 = b
63                         //a为假,则d11 = c
64 
65 //== waveform6 位运算符
66 //======================================================================
67 assign c11 = ~a;        //取反
68 assign c22 = a & b;     //按位与
69 assign c33 = a | b;     //按位或
70 assign c44 = a ^ b;     //按位异或
71 assign c55 = a ~^ b;    //按位同或
72 assign c66 = a ^~ b;    //按位同或
73 
74 //== waveform7 移位运算符 
75 //======================================================================
76 assign e11 = a << b;    //左移
77 assign e22 = a >> b;    //右移
78 
79 //== waveform8 位拼接运算符
80 //======================================================================
81 assign f11 = {a , b};   //拼接a和b,a和b位宽均为4,f11位宽为8
82 assign f22 = {2'd2{b}}; //拼接b低2位
83 
84 endmodule
View Code

 

  2.三人表决器 --- 结构描述方式

 1 module Example_Structure
 2 (
 3     input       A   ,   //模块的输入端口A
 4     input       B   ,   //模块的输入端口B
 5     input       C   ,   //模块的输入端口C
 6     output      L       //模块的输出端口L
 7 );
 8 
 9 //== 信号定义
10 //======================================================================
11 wire AB,BC,AC;          //内部信号声明AB,BC,AC
12 
13 and U1(AB,A,B);         //与门(A,B信号进入)(A与B信号即AB输出)          
14 and U2(BC,B,C);         //与门 同上
15 and U3(AC,A,C);         //与门 同上
16   
17 or  U4(L,AB,BC,AC);     //或门 同上
18      
19 endmodule
View Code

 

  3.三人表决器 --- 数据流描述方式

 1 module Example_Dataflow
 2 (
 3     input   A   ,     //模块的输入端口A
 4     input   B   ,     //模块的输入端口B
 5     input   C   ,     //模块的输入端口C
 6     output  L         //模块的输出端口L
 7 );
 8 
 9 assign L = ((!A) & B & C) | (A & (!B) & C) | (A & B & (!C)) | (A & B & C);
10 
11 endmodule
View Code

 

  4.三人表决器 --- 行为描述方式

 1 module Example_Behavior
 2 (
 3     input           A   ,    //模块的输入端口A
 4     input           B   ,    //模块的输入端口B
 5     input           C   ,    //模块的输入端口C
 6     output reg      L        //模块的输出端口L
 7 );
 8 
 9 always @(A,C,B)begin        //敏感列表只需要A、B、C,也可以写成always @(*)
10     case({A,B,C})           //注意{A,B,C}是位拼接,合成一条总线
11         3'b000: L = 1'b0;
12         3'b001: L = 1'b0;
13         3'b010: L = 1'b0;
14         3'b011: L = 1'b1;
15         3'b100: L = 1'b0;
16         3'b101: L = 1'b1;
17         3'b110: L = 1'b1;
18         3'b111: L = 1'b1;
19         default:L = 1'bx;   //default不要省略
20     endcase
21 end
22 
23 endmodule
View Code

 

   5.模块化设计实现半加器

 1 module Example_Module
 2 (
 3     input       a       ,
 4     input       b       ,
 5     output      s       ,
 6     output      c
 7 );
 8 
 9 //== 实例化 与门
10 //======================================================================
11 Example_yumen yumen_module
12 (
13     .yumen_a(a),
14     .yumen_b(b),
15     .yumen_c(c)
16 );
17 
18 //== 实例化 异或
19 //======================================================================
20 Example_yihuo yihuo_module
21 (
22     .yihuo_a(a),
23     .yihuo_b(b),
24     .yihuo_s(s)
25 );
26 
27 endmodule
Top

 

 1 module Example_yihuo
 2 (
 3     input       yihuo_a     ,
 4     input       yihuo_b     ,
 5     output      yihuo_s
 6 );
 7 
 8 assign yihuo_s = yihuo_a ^ yihuo_b;
 9 
10 endmodule
Yihuo

 

 1 module Example_yumen
 2 (
 3     input       yumen_a     ,
 4     input       yumen_b     ,
 5     output      yumen_c
 6 );
 7 
 8 assign yumen_c = yumen_a && yumen_b;
 9 
10 endmodule
Yumen

 

6.8-1数据选择器

 1 module Digital_Selector
 2 (
 3     input               D0          ,
 4     input               D1          ,
 5     input               D2          ,
 6     input               D3          ,
 7     input               D4          ,
 8     input               D5          ,
 9     input               D6          ,
10     input               D7          ,
11     input      [ 2:0]   A           ,
12     output reg [ 7:0]   Y
13 );
14 
15 always @(*)begin
16     case(A)
17         3'b000 : Y = D0;
18         3'b001 : Y = D1;
19         3'b010 : Y = D2;
20         3'b011 : Y = D3;
21         3'b100 : Y = D4;
22         3'b101 : Y = D5;
23         3'b110 : Y = D6;
24         3'b111 : Y = D7;
25         default: Y = 1'b0;
26     endcase
27 end
28 
29 endmodule
View Code

 

 

7.8-3编码器

 1 module Digital_Encoder
 2 (
 3     input      [ 7:0]   I               ,
 4     output reg [ 2:0]   A
 5 );
 6 
 7 //== case判断I,8位数转为3位数
 8 //======================================================================
 9 always @(*)begin
10     case(I)
11         8'b0000_0001 : A = 3'b000;
12         8'b0000_0010 : A = 3'b001;
13         8'b0000_0100 : A = 3'b010;
14         8'b0000_1000 : A = 3'b011;
15         8'b0001_0000 : A = 3'b100;
16         8'b0010_0000 : A = 3'b101;
17         8'b0100_0000 : A = 3'b110;
18         8'b1000_0000 : A = 3'b111;
19         default:       A = 3'b000;
20     endcase
21 end
22 
23 
24 /*
25 //== if...else优先级写法,优先级从上到下
26 //======================================================================
27 always @(*)begin
28     if(I[7] == 1'b0)          A = 3'b000;
29     else if(I[6] == 1'b0)     A = 3'b001;
30     else if(I[5] == 1'b0)     A = 3'b010;
31     else if(I[4] == 1'b0)   A = 3'b011;
32     else if(I[3] == 1'b0)     A = 3'b100;
33     else if(I[2] == 1'b0)     A = 3'b101;
34     else if(I[1] == 1'b0)     A = 3'b110;
35     else if(I[0] == 1'b0)    A = 3'b111;
36     else                      A = 3'b000;
37 end
38 */
39 
40 endmodule
View Code

 

8.3-8译码器

 1 module Digital_Decoder
 2 (
 3     input      [ 2:0]   A           ,
 4     output reg [ 7:0]   I
 5 );
 6 
 7 always @(*)begin
 8     case(A)
 9         3'b000 : I = 8'b01111111;
10         3'b001 : I = 8'b10111111;
11         3'b010 : I = 8'b11011111;
12         3'b011 : I = 8'b11101111;
13         3'b100 : I = 8'b11110111;
14         3'b101 : I = 8'b11111011;
15         3'b110 : I = 8'b11111101;
16         3'b111 : I = 8'b11111110;
17         default: I = 8'b11111111;
18     endcase
19 end
20 
21 endmodule
View Code

 

9.D触发器

 1 module Digital_Data_Flip_Flop
 2 (
 3     input               clk         ,
 4     input               rst_n       ,
 5     input               D           ,
 6     output reg          Q
 7 );
 8 
 9 always @(posedge clk or negedge rst_n)begin
10     if(!rst_n)
11         Q <= 1'b0;
12     else
13         Q <= D;
14 end
15 
16 endmodule
View Code

 

10.4bit移位寄存器

 1 module Digital_Shift_Reg
 2 (
 3     input               clk         ,
 4     input               rst_n       ,
 5     input               data_in     ,
 6     input               data_en     ,
 7     output reg [ 3:0]   data_out    ,
 8     output reg [ 3:0]   data_out_n
 9 );
10 
11 //== 时序逻辑,寄存data_out_n的值,所以看起来比data_out_n慢一拍
12 //======================================================================
13 always @(posedge clk or negedge rst_n)begin
14     if(!rst_n)
15         data_out <= 4'b0;
16     else
17         data_out <= data_out_n;
18 end
19 
20 //== 组合逻辑,不断移位
21 //======================================================================
22 always @(*)begin
23     if(data_en)
24         data_out_n = {data_out[2:0],data_in};
25     else
26         data_out_n = data_out;
27 end
28 
29 /*----------------------------------------------------------------------
30 --补充:如果要实现循环右移,则写成[data_in,data_out[3:1]]
31 ----------------------------------------------------------------------*/
32 
33 
34 endmodule
View Code

 

11.反馈回环的正误解析

 1 //== 错误写法:data_out既是条件又是结果
 2 //======================================================================
 3 module Example_Feedback
 4 (
 5     input     data_in1    ,
 6     input     data_in2    ,
 7     output     data_out
 8 );
 9                             //data_out是最终结果,可又是形成条件
10 assign data_out = (data_in2) ? data_in1 : (~data_out | data_in1);
11 
12 endmodule
13 
14 
15 /*
16 //== 正确写法:用data_out_r寄存一下,再给data_out
17 //======================================================================
18 module Example_Feedback
19 (
20     input     clk         ,
21     input     rst_n       ,
22     input     data_in1    ,
23     input     data_in2    ,
24     output     data_out
25 );
26 
27 //信号定义
28 reg         data_out_r  ;
29 
30 //时序逻辑,寄存结果
31 always @ (posedge clk or negedge rst_n)
32 begin
33     if(!rst_n)
34         data_out_r <= 1'b0;
35     else
36         data_out_r <= (data_in2) ? (data_in1) : (~data_out_r | data_in1);
37 end
38 
39 //寄存后的结果再输出
40 assign data_out = data_out_r;
41 
42 endmodule
43 */
View Code

12.阻塞赋值和非阻塞赋值

 1 module Example_Block
 2 (
 3     input        clk             ,
 4     input        block_in        ,
 5     output         block_out1      ,
 6     output         block_out2      ,
 7     output         no_block_out1   ,
 8     output         no_block_out2
 9 );
10 
11 //block模块例化
12 block block_init
13 (
14     .clk            (clk        ),
15     .block_in        (block_in    ),
16     .block_out1        (block_out1    ),
17     .block_out2        (block_out2    )
18 );
19 
20 //no_block模块例化
21 no_block no_block_init
22 (
23     .clk            (clk            ),
24     .no_block_in    (block_in        ),
25     .no_block_out1    (no_block_out1    ),
26     .no_block_out2    (no_block_out2    )
27 );
28 
29 endmodule
Top

 

 1 module block
 2 (
 3     input        clk         ,
 4     input        block_in    ,
 5     output reg  block_out1  ,
 6     output reg  block_out2
 7 );
 8 
 9 always @(posedge clk)begin
10     block_out1 = block_in;
11     block_out2 = block_out1;
12 end
13 
14 endmodule
Block

 

 1 module no_block
 2 (
 3     input        clk             ,
 4     input        no_block_in     ,
 5     output reg  no_block_out1   ,
 6     output reg  no_block_out2
 7 );
 8 
 9 always @(posedge clk)begin
10     no_block_out1 <= no_block_in;
11     no_block_out2 <= no_block_out1;
12 end
13 
14 endmodule
no_Block

 

 

  这些基础数字电路的Verilog描述应该非常熟悉,才能够为后面的学习打下扎实的基础。

 

参考资料:[1]锆石科技FPGA教程

posted @ 2018-11-20 17:25  咸鱼IC  阅读(2983)  评论(3编辑  收藏  举报