├── img ├── foo_logic.png └── uart_protocol.png ├── LICENSE └── README.md /img/foo_logic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZJUArch/verilog-general-guide/HEAD/img/foo_logic.png -------------------------------------------------------------------------------- /img/uart_protocol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZJUArch/verilog-general-guide/HEAD/img/uart_protocol.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 ZJU Architecture System Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Verilog General Guide 2 | 3 | This document aims to provide general guide to writing Verilog HDL. _Basic_ section focus on grammar with common fallacies and pitfalls, while _Advance_ section focus on style and common patterns. 4 | 5 | ## Basic 6 | 7 | ### What Verilog is and is not? 8 | 9 | We (students) use Verilog HDL to program FPGA. But it is necessary to know that Verilog is used in many other ways. Some tips are: 10 | 11 | - It is hardware **Description** Language (HDL). So you'd better know what hardware module (deep into circuit) you want to build before writing Verilog code. 12 | - It aims to replace schematic hardware description. 13 | - It is heavily used on simulation and behavior verification. 14 | - It is **NOT** C programming language. Do not think of software development when you are writing Verilog. 15 | - It is **NOT** completely synthesizable (only part of it). 16 | 17 | ### Verilog grammar quick walk through 18 | 19 | Attention: This chapter only contains Verilog grammar that is frequently used. Most "advanced grammar" is omitted. 20 | 21 | Pay great attention to those **bold words**. It indicates place where mistakes usually happen. 22 | 23 | #### Module 24 | 25 | A module is like a class in object oriented language. A simple module descripting a counter is like: 26 | 27 | ```verilog 28 | module counter( 29 | input clk, 30 | input reset, 31 | output [31:0] cnt 32 | ); 33 | 34 | reg [31:0] cnt_reg; 35 | 36 | always @(posedge clk) begin 37 | if (reset) begin 38 | cnt_reg <= 32'b0; 39 | end else begin 40 | cnt_reg <= cnt_reg + 1'b1; 41 | end 42 | end 43 | 44 | assign cnt = cnt_reg; 45 | 46 | endmodule 47 | ``` 48 | 49 | The type of a module port can be `input`, `output` or `inout` (rarely used, but couldn't be avoided in some cases). 50 | 51 | Using a module is like instantiate a class: 52 | 53 | ```verilog 54 | module top( 55 | input clk, 56 | input reset 57 | ); 58 | wire [31:0] cnt; 59 | 60 | counter counter( 61 | .clk(clk), 62 | .reset(reset), 63 | .cnt(cnt) 64 | ); 65 | 66 | endmodule 67 | ``` 68 | 69 | #### Variable 70 | 71 | `wire` and `reg` are two types that most commonly used. 72 | 73 | - `wire`: Physically a wire. Can not "hold" value. Must be continuously assigned. 74 | - `reg`: **Not necessarily** a register. Can "hold" value. Can be conditionaly assigned. 75 | 76 | #### Assignment 77 | 78 | `assign` keyword is used when assigning a wire (outside of always block). The value is continuous assigned to the wire. It makes sense because a physical wire always has a value (either high or low). 79 | 80 | `=` (block assignment) and `<=` (non-block assignment) operators are used when assign a reg. 81 | 82 | - block assignment: 83 | - evaluated and assgined in a single step. 84 | - execution flow within the procedure is blocked until the assignment is blocked. 85 | - usually used in combinational always block (Xilinx suggests never use block assignment in sequential logic even you can use them technically and the code sucessfully synthesizes) 86 | 87 | Block assignment example: 88 | 89 | ```verilog 90 | module foo_logic( 91 | input clk, 92 | input a, 93 | input b, 94 | input c, 95 | input sh 96 | ); 97 | reg data; 98 | 99 | // Though this varables is "reg" type, it is physically a wire. 100 | // We type it as "reg" so that we can use it in an always block with "if" and "else" condition 101 | reg data_in; 102 | 103 | always @* begin 104 | // provide default value 105 | data_in = 1'b0; 106 | if (a & ~sh) begin 107 | data_in = 1'b1; 108 | end else begin 109 | if (~data & (c & sh)) 110 | data_in = 1'b1; 111 | else if (data & (b & sh)) 112 | data_in = 1'b1; 113 | end 114 | end 115 | 116 | always @(posedge clk) begin 117 | data <= data_in; 118 | end 119 | 120 | endmodule 121 | ``` 122 | 123 | The diagram is: 124 | 125 | ![foo_logic](img/foo_logic.png) 126 | 127 | The module can be writen without combinational always block as: 128 | 129 | ```verilog 130 | module foo_logic( 131 | input clk, 132 | input a, 133 | input b, 134 | input c, 135 | input sh 136 | ); 137 | // This is the only real register 138 | reg data; 139 | 140 | wire q = data; 141 | wire notq = ~data; 142 | 143 | wire anda; 144 | wire andb; 145 | wire andc; 146 | wire andq; 147 | wire andqbar; 148 | wire orq; 149 | wire data_in; 150 | 151 | assign andc = c & sh; 152 | assign andb = b & sh; 153 | assign anda = a & ~sh; 154 | 155 | assign andq = andb & q; 156 | assign andqbar = andc & notq; 157 | 158 | assign orq = andq | andqbar; 159 | 160 | assign data_in = orq | anda; 161 | 162 | always @(posedge clk) begin 163 | data <= data_in; 164 | end 165 | 166 | endmodule 167 | ``` 168 | 169 | - Non-block assignment: happens parallel 170 | - evaluated and assigned in two steps: 171 | 1. The right The right-hand side is evaluated immediately hand side is evaluated immediately. 172 | 1. The assignment to the left-hand side is postponed until other evaluations in the current time step are completed. 173 | 174 | Non-block assignment example (swap value): 175 | 176 | ```verilog 177 | module flop( 178 | input clk, 179 | input reset 180 | ); 181 | reg flop1; 182 | reg flop2; 183 | 184 | always @(posedge clk) begin 185 | if (reset) begin 186 | flop1 <= 1'b0; 187 | flop2 <= 1'b1; 188 | end else begin 189 | flop1 <= flop2; 190 | flop2 <= flop1; 191 | end 192 | end 193 | 194 | endmodule 195 | ``` 196 | 197 | **Tip:** Always use block assignment in combinational logic (`always @*`), and non-block assignment in sequential logic (`always @(posedge clk)`). 198 | 199 | #### Operator 200 | 201 | - Logical: `!` `&&` `||` `==` `!=` 202 | - Bitwise: `~` `&` `|` `^` 203 | - Reduction: `&` `~&` `|` `~|` `^` 204 | - Shift: `<<` `>>` 205 | - Concatenation: `{}` 206 | - Replication: `{{}}` 207 | - Arithmetic: `+` `-` `*` 208 | - Division: `/` **(Support only if second operand is a power of 2 or Both operands are constant)** 209 | - Modulus: `%` **(Support only if second operand is a power of 2)** 210 | - Power: `**` **(Support if both operands are constants or first operand is 2)** 211 | 212 | #### Conditional branch 213 | 214 | - Wire assignment: `assign aWire = (a == b) ? 1: 0;` 215 | - Always block: `if … else …` 216 | - Yes, `if` and `else` statement is only available inside always block. 217 | - If you want to use it to assign a wire, declare that wire as reg and use it inside a `always @*` block. 218 | 219 | #### Always block 220 | 221 | - When a signal in sensitive list changes, the block content will be execute 222 | - Two common usage: 223 | - `always @*`: for combination logic 224 | - `*` equals to all the right hand variables inside that block or-ed together 225 | - `always @(posedge clk)`: for sequential logic 226 | 227 | **Tip:** It is preferable to use synchronize reset to maintain small time delay. For example: 228 | 229 | ```verilog 230 | always @(posedge clk) begin 231 | if (reset) begin 232 | // do initialization and/or reset 233 | end 234 | end 235 | ``` 236 | 237 | Instead of: 238 | 239 | ```verilog 240 | always @(posedge clk or negedge reset) begin 241 | if (!reset) begin 242 | // do initialization and/or reset 243 | end 244 | end 245 | ``` 246 | 247 | #### Parameter & local parameter 248 | 249 | In Verilog HDL, parameters are constants and do not belong to any other data type such as net or register data types. There are two types of parameters in Verilog, `parameter` and `localparam` (local parameter). 250 | 251 | `parameter` can be reassigned when initialization, see example below. 252 | 253 | `localparam` is of local usage. Can't be reassigned. 254 | 255 | `parameter` is a great tool for generic design, and `localparam` is usually used for state representation. For example: 256 | 257 | ```verilog 258 | module mux2to1( 259 | input [WIDTH-1:0] a, 260 | input [WIDTH-1:0] b, 261 | input sel, 262 | output [WIDTH-1:0] o 263 | ); 264 | 265 | parameter WIDTH = 32; 266 | 267 | assign o = sel ? b : a; 268 | 269 | endmodule 270 | ``` 271 | 272 | We can thus use the above module to create 32-bit, 16-bit, 8-bit 2 to 1 mux like this: 273 | 274 | ```verilog 275 | // default is 32-bit 276 | mux2to1 mux2to1_32bit (.a(a), .b(b), .sel(sel), .o(o)); 277 | 278 | // instantiate as 16-bit 279 | mux2to1 #(.WIDTH(16)) mux2to1_16bit (.a(a), .b(b), .sel(sel), .o(o)); 280 | 281 | // instantiate as 8-bit 282 | mux2to1 #(.WIDTH(8)) mux2to1_16bit (.a(a), .b(b), .sel(sel), .o(o)); 283 | ``` 284 | 285 | #### "Advance" grammar (you can live perfectly without them, so don’t panic) 286 | 287 | `function` and `task` are pretty much like `function` and `procedure` in Pascal. A function returns value while task doesn't. 288 | 289 | `generator` is the template which generate code before sythesizing. 290 | 291 | - function 292 | - task 293 | - generator 294 | 295 | Won't say too much about them because we are in _Basic_ section. But they are powerful and convenient when you get familiar with them. You may refer to other resource if you want to learn. 296 | 297 | ## Advance 298 | 299 | ### Rules 300 | 301 | 1. Prefer sync to async 302 | - Always use `posedge clk` to trigger a sequential always block instead of some random signals. 303 | - Reason: Eases clock network synthesis. Eases test strategy generation, and limits exceptions to the coding standards to a small module. It also improves the portability of the code to a different end use clocking scheme. 304 | 1. Prefer explicitly initialize in always block to initial block 305 | - Reseting reg value when `reset` signal is high. 306 | - Reason: Always maintaining proper reset behavior. 307 | 1. Prefer multiple always blocks to a huge always block 308 | - Reason: dividing different logic to make code clear. 309 | 1. Prefer generic design 310 | - Using `parameter` to write generic module 311 | - Reason: Simplify code. Increase readability. 312 | 1. Prefer semantic naming 313 | 1. Prefer unified coding sytle 314 | - Since Verilog coding style is rather complicated and various among different companies. We do not specify a certain style here. But make sure you stick to one through your project. 315 | 316 | ### Pattern 317 | 318 | #### Finite state machine 319 | 320 | Finite state machine (a.k.a. FSM) is the most important conception in hardware programming. You will use FSM a lot when you are trying to adapt hardware protocols. 321 | 322 | There are two types of FSM: 323 | 324 | 1. Moore machine: the next state is decided by current state. 325 | 2. Mealy machine: the next state is decided by current state along with input. 326 | 327 | Refer to text book or wiki if you don't understand. 328 | 329 | There exist a pattern to describe FSMs. The idea is to divide "next state" decision apart from "current state" action. 330 | 331 | For example, consider the UART protocol: 332 | 333 | ![uart_protocol](img/uart_protocol.png) 334 | 335 | Since we are just introducing the FSM pattern, we ignore the clock synchronization and over-sampling logic (if you don't know what it means, look it up). Assume that we managed to be triggered at sampling points just as the picture implies, we can model this protocol with `IDLE`, `RECEIVING`, `STOP` three state. The receiving module code could be: 336 | 337 | ```verilog 338 | /* 339 | * Caution! This code is meant to be introducing the FSM pattern. 340 | * It won't work if you don't add the clock synchronization and over-sampling logic. 341 | * You should write your own uart receiver instead of copying this one. 342 | */ 343 | module uart_receiver( 344 | input clk, 345 | input reset, 346 | input rx, 347 | output ready, 348 | output [7:0] data 349 | ); 350 | 351 | localparam 352 | IDLE = 0, 353 | RECEIVING = 1, 354 | STOP = 2; 355 | 356 | reg [7:0] shift_reg; 357 | reg ready_reg; 358 | 359 | reg [1:0] state; 360 | reg [1:0] state_next; 361 | 362 | reg [2:0] cnt; 363 | reg [2:0] cnt_next; 364 | 365 | // combinational logic only concerns what the next state is 366 | always @* begin 367 | // next state is default to current state 368 | state_next = state; 369 | cnt_next = cnt; 370 | case (state) 371 | IDLE: begin 372 | if (rx == 1'b0) begin 373 | state_next = RECEIVING; 374 | cnt_next = 3'b000; 375 | end 376 | end 377 | RECEIVING: begin 378 | if (cnt == 3'b111) begin 379 | state_next = STOP; 380 | cnt_next = 3'b000; 381 | end else begin 382 | cnt_next = cnt + 1'b1; 383 | end 384 | end 385 | STOP: begin 386 | // stop bit must be a "1", otherwise indicates an error 387 | // we assume errors never happen 388 | state_next = IDLE; 389 | end 390 | endcase 391 | end 392 | 393 | // sequential logic concerns what to do in current state 394 | always @(posedge clk) begin 395 | if (reset) begin 396 | cnt <= 3'b000; 397 | state <= IDLE; 398 | shift_reg <= 8'b0; 399 | ready_reg <= 1'b0; 400 | end else begin 401 | // transfer state 402 | cnt <= cnt_next; 403 | state <= state_next; 404 | 405 | case(state) 406 | IDLE: begin 407 | shift_reg <= 8'b0; 408 | ready_reg <= 1'b0; 409 | end 410 | RECEIVING: begin 411 | shift_reg <= {rx, shift_reg[6:1]}; 412 | end 413 | STOP: begin 414 | ready_reg <= 1'b1; 415 | end 416 | endcase 417 | end 418 | end 419 | 420 | assign ready = ready_reg; 421 | assign data = shift_reg; 422 | 423 | endmodule 424 | ``` 425 | 426 | ## Reference 427 | 428 | 1. Xilinx XST User Guide for Virtex-6, Spartan-6, and 7 Series Devices 429 | 2. Verilog HDL Coding by freescale semiconductor 430 | --------------------------------------------------------------------------------