|
|
|
|
|
|
|
|
|
|
|
|
Generate Blocks
|
|
|
This feature has been taken from VHDL with some modification. It is possible to use it for loops to mimic multiple instants. Below is an example of usage of Verilog 2001 generate statement. |
|
|
|
|
|
1 module generate_example();
2
3 reg read,write = 0;
4 reg [31:0] data_in = 0;
5 reg [3:0] address = 0;
6 wire [31:0] data_out;
7
8 initial begin
9 $monitor ("%g read=%b write=%b address=%b data_in=%h data_out=%h",
10 $time, read, write, address, data_in, data_out);
11 #1 read = 0; // why only for read
12 #3 repeat (16) begin
13 data_in = $random;
14 write = 1;
15 #1 address = address + 1;
16 end
17 write = 0;
18 address = 0;
19 #3 repeat (16) begin
20 read = 1;
21 #1 address = address + 1;
22 end
23 read = 0;
24 #1 $finish;
25 end
26
27 genvar i;
28
29 generate
30 for (i=0; i < 4; i=i+1) begin : MEM
31 memory U (read, write,
32 data_in[(i*8)+7:(i*8)],
33 address,data_out[(i*8)+7:(i*8)]);
34 end
35 endgenerate
36
37 endmodule
38
39 // Lower module that will be connected muliple times
40 module memory (
41 input wire read,
42 input wire write,
43 input wire [7:0] data_in,
44 input wire [3:0] address,
45 output reg [7:0] data_out
46 );
47
48 reg [7:0] mem [0:15];
49
50 always @ (*)
51 begin
52 if (write) mem[address] = data_in;
53 end
54
55 always @ (read, address)
56 begin
57 if (read) data_out = mem[address];
58 end
59
60 endmodule
You could download file generate_example.v here
|
|
|
|
|
|
Multi-Dimension Array
|
|
|
Verilog 1995 allows one-dimensional arrays of variables. Verilog 2001 allows more than two dimensions with support for arrays of variable and net data types. In array assignments, Verilog 2001 allows part selection and variables to be used in part selection as shown in the example below. |
|
|
|
|
|
1 module multi_array();
2
3 reg read_v95, read_multi, read_bit;
4
5 // Verilog 1995 and Verilog 2001 allow
6 // 1 dimensional arrays
7 reg [7:0] address;
8 reg [7:0] memory [0:255];
9 wire [7:0] data_out;
10
11 assign data_out = (read_v95) ? memory[address] : 0;
12
13 // Verilog 2001 allows multi dimension arrays
14 reg [7:0] address1, address2;
15 reg [15:0] array [0:255][0:255];
16 wire [7:0] data_array = (read_multi) ? array[address1][address2] : 0;
17
18 // Verilog 2001 allows bit and part select within arrays
19 wire [7:0] data_bit = (read_bit) ? array[1][200][12:5] : 8'b0;
20
21 // Verilog 2001 allows indexed vector part selects
22 reg [31:0] double_word;
23 reg [2:0] byte_no;
24 wire [7:0] pos_offset = double_word[byte_no*8 +:8];
25 wire [7:0] neg_offset = double_word[byte_no*8 -:8];
26
27 initial begin
28 // Check bit and part select within array
29 #1 array[1][200] = 16'h1234;
30 #1 read_bit = 1;
31 #1 array[1][200] = 16'hAAAA;
32 // Check indexed vector part selects
33 double_word = 32'hDEAD_BEEF;
34 #1 byte_no = 2;
35 #1 byte_no = 1;
36 #1 $finish;
37 end
38
39 always @ (*)
40 $display (
41 "double_word : %h byte_no : %d pos_offset : %h neg_offset : %h",
42 double_word, byte_no, pos_offset, neg_offset);
43
44 always @ (*)
45 $display ("array[1][200] : %h read_bit : %b data_bit : %h",
46 array[1][200],read_bit, data_bit);
47
48 endmodule
You could download file multi_array.v here
|
|
|
|
|
|
Re-entrant tasks and recursive functions
|
|
|
Verilog 2001 adds a new keyword: automatic. This keyword, when added to a task, makes the task re-entrant. All task declarations with automatic are allocated dynamically for each concurrent task entry. |
|
|
|
|
|
A function with added automatic keyword allows the function to be called recursively. |
|
|
|
|
|
|
|
|
|
|
|
Example : Task
|
|
|
|
|
|
1 module re_entrant_task();
2
3 task automatic print_value;
4 input [7:0] value;
5 input [7:0] delay;
6 begin
7 #(delay) $display("%g Passed Value %d Delay %d", $time, value, delay);
8 end
9 endtask
10
11 initial begin
12 fork
13 #1 print_value (10,7);
14 #1 print_value (8,5);
15 #1 print_value (4,2);
16 join
17 #1 $finish;
18 end
19
20 endmodule
You could download file re_entrant_task.v here
|
|
|
|
|
|
Example : Function
|
|
|
|
|
|
1 module recursuve_function();
2
3 function automatic [31:0] calFactorial;
4 input [7:0] number;
5 begin
6 if (number == 1) begin
7 calFactorial = 1;
8 end else begin
9 calFactorial = number * (calFactorial(number - 1));
10 end
11 end
12 endfunction
13
14 initial begin
15 $display ("Factorial of 1 : %d", calFactorial(1));
16 $display ("Factorial of 4 : %d", calFactorial(4));
17 $display ("Factorial of 8 : %d", calFactorial(8));
18 $display ("Factorial of 16 : %d", calFactorial(16));
19 $display ("Factorial of 32 : %d", calFactorial(32));
20 #1 $finish;
21 end
22
23 endmodule
You could download file recursive_function.v here
|
|
|
|
|
|
In-line parameter passing by name
|
|
|
Verilog 1995 allows 2 ways to override parameters declared in a module: |
|
|
|
|
|
|
|
|
|
|
|
Verilog 2001 adds a way to fix the problems that are introduced by # usage. This is done as with port connection by name, i.e. parameter are overridden by name rather than by position. |
|
|
|
|
|
1 module parameter_v2k();
2 parameter D_WIDTH = 4;
3 parameter A_WIDTH = 9;
4
5 reg [A_WIDTH-1:0] address = 0;
6 reg [D_WIDTH-1:0] data_in = 0;
7 wire [D_WIDTH-1:0] data_out;
8 reg rd,wr;
9
10 initial begin
11 $monitor ("%g addr %d din %h dout %d read %b write %b",
12 $time, address, data_in, data_out, rd, wr);
13 rd = 0;
14 wr = 0;
15 #1 repeat (10) begin
16 wr = 1;
17 data_in = $random;
18 #1 address = address + 1;
19 end
20 wr = 0;
21 address = 0;
22 data_in = 0;
23 #1 repeat (10) begin
24 rd = 1;
25 #1 address = address + 1;
26 end
27 rd = 0;
28 #1 $finish;
29 end
30
31 memory #(.AWIDTH(A_WIDTH),.DWIDTH(D_WIDTH)) U (
32 address, data_in, data_out, rd, wr);
33
34 endmodule
35
36 // Memory model
37 module memory (address, data_in, data_out, rd, wr);
38 parameter DWIDTH = 8;
39 parameter AWIDTH = 8;
40 parameter DEPTH = 1 << AWIDTH;
41
42 input [AWIDTH-1:0] address;
43 input [DWIDTH-1:0] data_in;
44 output [DWIDTH-1:0] data_out;
45 input rd,wr;
46
47 reg [DWIDTH-1:0] mem [0:DEPTH-1];
48
49 always @ (*)
50 if (wr) mem[address] = data_in;
51
52 assign data_out = (rd) ? mem[address] : 0;
53
54 endmodule
You could download file parameter_v2k.v here
|
|
|
|
|
|
Random Generator
|
|
|
In Verilog 1995, each simulator used to implement its own version of $random. In Verilog 2001, $random is standardized, so that simulations run across all simulators with out any inconsistency. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|