Commit fb5df750 authored by Alan Wood's avatar Alan Wood

Merge branch 'andrew-tutorial-tweaks' into 'tutorial'

Andrew tutorial tweaks

This is the first time I've tried GitLab so I don't know if I've got the process right...

See merge request !6
parents 934a2c60 65dd3e62
......@@ -52,14 +52,14 @@ assign y = a2[1] | a2[0];
## Concatenation and Replication
```verilog
assign y2 = {a,b};
assign y2 = {a,1'b0};
assign y3 = {a,b,1'b1};
assign y3 = {a,2'b10};
assign y3 = {a,a2};
assign y3 = {a,a2[0],1'b1};
assign {y2,y} = {y3[1:0],a};
assign y3 = {a,2{1'b1}};
assign y2 = {a,b}; // creates a 2-bit signal of a with b
assign y2 = {a,1'b0}; // a with 1 bit binary 0 (constant)
assign y3 = {a,b,1'b1}; // a with b with binary 1 (constant)
assign y3 = {a,2'b10}; // a with 2 binary bits 1, 0
assign y3 = {a,a2}; // a with a2 (a2 is 2 bits)
assign y3 = {a,a2[0],1'b1}; // a with single bit from a2 with 1
assign {y2,y} = {y3[1:0],a}; // multiple assignment: creates y2 as 2 bits from y3 and y as a
assign y3 = {a,2{1'b1}}; // a with 2 lots of binary 1
```
## Shifting
......@@ -83,6 +83,7 @@ assign y3 = {y3[0],y3[2:1]};
```
### Rotate right 2 bit
```verilog
assign y3 = {y3[1:0],y3[2]};
```
......@@ -103,6 +104,8 @@ assign max = (a > b) ? a : b;
## If/Else
(NB not sequential, actually 'network routings')
```verilog
if(a < b)
assign min = a;
......@@ -121,7 +124,7 @@ else
```verilog
if(boolean)
begin
begin // need begin...end if >1 line of code within condition
// begin code
end
else
......@@ -132,7 +135,7 @@ else
## Synthesis of Z and X Values
Z values can only be synthesised by tristate bufferes and thus infer them
Z values can only be synthesized by tristate buffers and thus infer them
these have output enable inputs to control their output state for example here
is a single bit tristate buffer with an output enable
......@@ -167,14 +170,13 @@ always @(sensitivity list)
end [optional label]
```
### Procedual Assignment
### Procedural Assignment
```verilog
[variable] = [expression]; // blocking, assigned before next statement
// like normal C
[variable] <= [expression]; // non blocking, assigned at end of always
// block
[variable] <= [expression]; // non blocking, assigned at end of always block
```
Blocking tends to be used for combinational circuits, non-blocking for
......@@ -185,7 +187,7 @@ with one of the variable data types, which are reg, integer, real, time, and
realtime. The reg data type is like the wire data type but used with a
procedural output. The integer data type represents a fixed-size (usually 32
bits) signed number in 2's-complement format. Since its size is fixed, we
usually don't use it in synthesis. The other data types are for modeling and
usually don't use it in synthesis. The other data types are for modelling and
simulation and cannot be synthesized.
## Registers
......@@ -194,7 +196,7 @@ A register is simple memory wire to hold state, normally implemented as
D-Types
```verilog
output reg
output reg // single-bit, use [] syntax above for >1 bit registers
```
## Conditional Examples
......@@ -212,7 +214,7 @@ en a1 a2 y
```verilog
module pri_encoder
(
( // 4 bit input, 3 bit output
input wire [4:1] r,
output wire [2:0] y
)
......@@ -239,9 +241,9 @@ module decoder_1
input wire en,
output reg [3:0] y
)
always @*
always @* // @* means 'Anything needed'; clearer to list required resources but danger of missing items
if(~en)
y = 4'b0000;
y = 4'b0000; // 4-bit wide, binary representation: 0000
else if(a == 2'b00)
y = 4'b0001;
else if(a == 2'b01)
......@@ -324,7 +326,7 @@ case statement. When synthesized, a parallel case statement usually infers a
multiplexing routing network and a non-parallel case statement usually infers
a priority routing network. Unlike C where conditional constructs are executed
serially using branches and jumps, with HDL these are realised by routing
netowrks.
networks.
### Casez
......@@ -338,7 +340,7 @@ module decoder_4
always @*
casez ({en,a})
3'b0??: y = 4'b0000;
3'b0??: y = 4'b0000; // casez also offers '?'
3'b100: y = 4'b0001;
3'b101: y = 4'b0010;
3'b110: y = 4'b0100;
......@@ -366,8 +368,8 @@ always @*
y = a & b;
```
`y` is the output of two circuits which could be contridictary, this is not
synthesiseable. Below is how this should have been writtten:
`y` is the output of two circuits which could be contradictary, this is not
synthesizable. Below is how this should have been written:
```verilog
always @*
......@@ -380,7 +382,7 @@ always @*
### Incomplete sensitivity list
Incomplete sensitivity list (missing `b`). `b` could change but the y output
would not, causing unexpected behavior againg this is not synthesiseable.
would not, causing unexpected behaviour again this is not synthesizable.
```verilog
always @(a)
......@@ -404,10 +406,10 @@ always @*
gt = 1'b1; // no eq assignment in branch
else if(a == b)
eq = 1'b1; // no gt assignment in branch
// final else branch omiitted
// final else branch omitted
```
Here we break both incomplete output assinment rules and branch According to
Here we break both incomplete output assignment rules and branch. According to
Verilog definition `gt` and `eq` keep their previous values when not assigned
which implies internal state, unintended latches are inferred, these sort of
issues cause endless hair pulling avoid such things. Here is how we could
......@@ -451,9 +453,9 @@ Similar errors can creep into case statements
```verilog
case(a)
2'b00: y =1'b1;
2'b10: y =1'b0;
2'b11: y =1'b1;
2'b00: y = 1'b1;
2'b10: y = 1'b0;
2'b11: y = 1'b1;
endcase
```
......@@ -473,21 +475,21 @@ endcase
## Adder with carry
```verilog
module adder #(parameter N=4)
module adder #(parameter N=4) // input parameter N, default value of 4 if not specified. N will be the adder width here
(
input wire [N-1:0] a,b,
output wire [N-1:0] sum,
output wire cout
output wire cout // carry bit
);
/* Constant Declaration */
localparam N1 = N-1;
localparam N1 = N-1; // localparam: only visible within module
/* Signal Declaration */
wire [N:0] sum_ext;
wire [N:0] sum_ext; // NB not N-1
/* module body */
assign sum_ext = {1'b0, a} + {1'b0, b};
assign sum_ext = {1'b0, a} + {1'b0, b}; // excludes Nth bit
assign sum = sum_ext[N1:0];
assign cout = sum_ext[N];
......@@ -499,7 +501,7 @@ module adder_example
output wire [3:0] sum4,
output wire c4
)
// Instantiate a 4 bit adder
// Instantiate a 4 bit adder - .N specifies parameter name N; connect a to a4, b to b4, sum to sum4, cout to c4
adder #(.N(4)) four_bit_adder (.a(a4), .b(b4), .sum(sum4), .cout(c4));
endmodule
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment