SV_2_verilog基础
1. verilog 的一般设计流程:
1. specification(specs)
2. high level design
3. low level (micro) design
4. RTL coding
5. verification
2. 以一个arbiter为例
Specs
- Two agent arbiter;
- Active hogh asynchronous reset;
- Fixed priority,with agent 0 have priority over agent 1;
- Grant will be asserted as long as request is asserted.
Block diagram of aribiter

从模块图中我们可以清楚的看出端口的数量以及数据的流向,甚至对于一些简单的设计我们也能根据模块图画出真值表,卡诺图进一步简化电路设计,但是对于一些大型的设计就会变得复杂,需要更有利的工具来帮助设计。
Design

对于一个简单的仲裁器来说,可以画出如上的状态图。圆圈代表着状态,箭头代表着数据的流向。状态机可以明确的之处设计的所有逻辑。
RTL Coding(partly)
module arbiter ( // Two slashes make a comment line. clock , // clock reset , // Active high, syn reset req_0 , // Request 0 req_1 , // Request 1 gnt_0 , // Grant 0 gnt_1 // Grant 1 ); //-------------Input Ports----------------------------- // Note : all commands are semicolon-delimited input clock ; input reset ; input req_0 ; input req_1 ; //-------------Output Ports---------------------------- output gnt_0 ; output gnt_1 ;
//arbiter block always @ (posedge clock) if (reset) begin gnt_0 <= 0; gnt_1 <= 0; end else if (req_0) begin gnt_1 <= 0; gnt_0 <= 1; end else if (gnt_1) begin gnt_0 <= 0; gnt_1 <= 1; end
else begin gnt_0 <= gnt_0; gnt_1 <= gnt_1; end
endmodule
3. 数据类型:
-
wire : 只能用于输出;
-
reg: 储存数据,可用于输入与输出;
- ...
4. 操作符
|
5. 控制语句(control statement)
if - else
// begin and end act like curly braces in C/C++. if (enable == 1'b1) begin data = 10; // Decimal assigned address = 16'hDEAD; // Hexadecimal wr_enable = 1'b1; // Binary end else begin data = 32'b0; wr_enable = 1'b0; address = address + 1; end
没有else语句也可以,但容易导致锁存,电路综合时出现latch
case
case(address) 0 : $display ("It is 11:40PM"); 1 : $display ("I am feeling sleepy"); 2 : $display ("Let me skip this tutorial"); default : $display ("Need to complete"); endcase
如同if - else 一样,如果case语句不能覆盖所有情况且没有default语句,电路综合时也可能出现不想要的锁存,latch。
while
while (free_time) begin $display ("Continue with webpage development"); end
Verilog中用的最多的一种结构:
1 module counter (clk,rst,enable,count); 2 input clk, rst, enable; 3 output [3:0] count; 4 reg [3:0] count; 5 6 always @ (posedge clk or posedge rst) 7 if (rst) begin 8 count <= 0; 9 end else begin : COUNT 10 while (enable) begin 11 count <= count + 1; 12 disable COUNT; 13 end 14 end 15 16 endmodule
For loop
1 for (i = 0; i < 16; i = i +1) begin 2 $display ("Current value of i is %d", i); 3 end
在verilog中不可使用++,--的操作符,只可使用i = i + 1。
Repeat
不同于for循环制定一个变量,使其自动递增想要的结果,repeat是显示指定一个循环数,以达到想要的结果。
1 repeat (16) begin 2 $display ("Current value of i is %d", i); 3 i = i + 1; 4 end
6. 变量赋值(Variable Assignment)
- 组合逻辑元素只能用assign 和 always 逻辑块赋值;
- 时序逻辑元素只能用always 逻辑块赋值;
- initial逻辑块只能同于testbench。
initial
1 initial begin 2 clk = 0; 3 reset = 0; 4 req_0 = 0; 5 req_1 = 0; 6 end
Initial 块只在仿真开始执行一次。
always
always块与initial块不同的是,always在敏感列表满足时总是执行,块内不能驱动wire类型,只能驱动reg和integer类型。
1 always @ (a or b or sel)//电平敏感 2 begin 3 y = 0; 4 if (sel == 0) begin 5 y = a; 6 end else begin 7 y = b; 8 end 9 end
电平敏感常被综合为组合逻辑电路,赋值方式为阻塞赋值“=”。
1 always @ (posedge clk )//边沿敏感 2 if (reset == 0) begin 3 y <= 0; 4 end else if (sel == 0) begin 5 y <= a; 6 end else begin 7 y <= b; 8 end
边沿敏感常被综合为时序逻辑电路,赋值方式为非阻塞赋值“<=”。
1 //无敏感列表,下面的例子用于生成时钟,(#5表示延时5个时间单位) 2 always begin 3 #5 clk = ~clk; 4 end
Assign statement
只对组合逻辑建模,并且会连续执行,所以assign语句又称为“连续赋值语句”。
1 assign out = (enable) ? data : 1'bz;
1 assign out = data;
7. 任务和函数(Task and Function)
函数和任务用来定义一一些需要反复运行的动作。
语法相同;不同点在于:
- task:可以有延迟;可用于时序电路和组合电路;
- function:不可以有延迟,只能用于组合电路。
7. Test Benches
tesebench是用来测试所设计的模块是否符合前期规范的要求。
一个典型的用来测试仲裁器的testbench
1 module arbiter ( 2 clock, 3 reset, 4 req_0, 5 req_1, 6 gnt_0, 7 gnt_1 8 ); 9 10 input clock, reset, req_0, req_1; 11 output gnt_0, gnt_1; 12 13 reg gnt_0, gnt_1; 14 15 always @ (posedge clock or posedge reset) 16 if (reset) begin 17 gnt_0 <= 0; 18 gnt_1 <= 0; 19 end else if (req_0) begin 20 gnt_0 <= 1; 21 gnt_1 <= 0; 22 end else if (req_1) begin 23 gnt_0 <= 0; 24 gnt_1 <= 1; 25 end 26 27 endmodule 28 // Testbench Code Goes here 29 module arbiter_tb; 30 31 reg clock, reset, req0,req1; 32 wire gnt0,gnt1; 33 34 initial begin 35 $monitor ("req0=%b,req1=%b,gnt0=%b,gnt1=%b", req0,req1,gnt0,gnt1); 36 clock = 0; 37 reset = 0; 38 req0 = 0; 39 req1 = 0; 40 #5 reset = 1; 41 #15 reset = 0; 42 #10 req0 = 1; 43 #10 req0 = 0; 44 #10 req1 = 1; 45 #10 req1 = 0; 46 #10 {req0,req1} = 2'b11; 47 #10 {req0,req1} = 2'b00; 48 #10 $finish; 49 end 50 51 always begin 52 #5 clock = !clock; 53 end 54 55 arbiter U0 ( 56 .clock (clock), 57 .reset (reset), 58 .req_0 (req0), 59 .req_1 (req1), 60 .gnt_0 (gnt0), 61 .gnt_1 (gnt1) 62 ); 63 64 endmodule
1 //simulation result 2 req0=0,req1=0,gnt0=x,gnt1=x 3 req0=0,req1=0,gnt0=0,gnt1=0 4 req0=1,req1=0,gnt0=0,gnt1=0 5 req0=1,req1=0,gnt0=1,gnt1=0 6 req0=0,req1=0,gnt0=1,gnt1=0 7 req0=0,req1=1,gnt0=1,gnt1=0 8 req0=0,req1=1,gnt0=0,gnt1=1 9 req0=0,req1=0,gnt0=0,gnt1=1 10 req0=1,req1=1,gnt0=0,gnt1=1 11 req0=1,req1=1,gnt0=1,gnt1=0 12 req0=0,req1=0,gnt0=1,gnt1=0
注意:输出为wire或reg,输入为reg
浙公网安备 33010602011771号