summaryrefslogtreecommitdiff
path: root/16.md
blob: 9320ffb033a5573c0079f1bbd4180d9c7e43af75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
[\<- Datapath concepts : buses, registers, multi-bit muxes, shift registers](15.md)

---

# Procedural Verilog and specifying sequential circuits in Verilog

## Conditional assignment

- Mux can be modeled as a conditional assign statement
	- Mux select is condition
	- "Port1" listed first

```
module mux2to1(20, 21, s, f);
	input w0, w1, s;
	output f;

	assign f = s ? w1 : w0;

endmodule
```

---

## "Always" block concepts

### Strange concepts ahead

- The next topic we will be looking at is the concept of procedural statements
	- Often referred to as an "always" block because it starts with the keyword "always"
- Can be a difficult concept to wrap your head around
	- Prime example of the idiosyncrasies of how Verilog was developed
- Once you get the hang of it, makes Verilog so much easier to specify complex circuits
- Always keep in mind that we are **describing hardware**, not writing software code

### The always block

- Assign statements are a relatively direct modeling of hardware concepts
- Always block allows for specifying functionality in a high-level fashion
	- Simulation tools interpret the behavior
	- Synthesis tools translate into an implementation structure
		- Quartus doesn't implement structure you specify
- Code inside block evaluated sequentially
- Use of begin/end for multiple statements

### Sensitivity list

- Most uses of always block use an `@` construct to indicate when block should be evaluated
	- Called the sensitivity list
- Might be easier to think of "always" as "whenever"
- For combinational logic, needs to list all inputs to the logic
	- Originally required complete listing
	- At some point, `*` (wildcard) was added as a convenience

### The "reg" variable type

- As with other languages, variables are set to values when on left of equal sign
	- `A = B & C`
- Sometimes an always block doesn't execute
	- Conditions in sensitivity list not met
- Simulator needs to maintain variable settings from the last time the always block \*did\* execute
	- Led to requiring variables to be of type "reg"

---

### If-statement examples

### Mux with if-else statement

- If-else construct doesn't as obviously match a hardware structure, but is useful for specifying behavior
- `f` is defined as reg, as well as output
	- It needs to be declared as reg because it is being used in the always block

```
module mux2to1(w0, w1, s, f);
	input w0, w1, s;
	output reg f;

	always @(w0, w1, s)
		if (s==0)
			f = w0;
		else
			f = w1;
	
endmodule
```

### A few other constructs

- Buses are like arrays
	- wire [1:0] S; (or [0:1] S)
	- Individual bits/wires can be identified: S[1]
- Buses can be "created" by concatenation
	- S[1:0] = {S1, S0}
- Specifying constants: \<n\>'b\<bit pattern\>
	- 2'b11
	- Can also do 4'hF (== 4'b1111)
	- n is the number of bits, not the # of digits
	- b vs h indicates format of constant (binary vs hex)

### 4:1 mux using always @(\*)

- The wildcard is used in place of listing out all our inputs

```
module mux4to1(w0, w1, w2, w3, S, f);
	input w0, w1, w2, w3;
	input [1:0] S;
	output reg f;

	always @(*)
		if(S == 2'b00)
			f = w0;
		else if(S == 2'b01)
			f = w1;
		else if (S == 2'b10)
			f = w2;
		else if (S == 2'b11)
			f = w3;

endmodule
```

### Bus enumeration

- Example of both styles: 0:3 and 1:0

```
module mux4to1(W, S, f);
	input [0:3] W;
	input [1:0] S;
	output reg f;

	always @(W, S)
		if(S == 0)
			f = W[0];
		else if(S == 1)
			f = W[1];
		else if (S == 2)
			f = W[2];
		else if (S == 3)
			f = W[3];

endmodule
```

---

## Case-statement examples

### The case statement

- Each 'if' clause is checking for a different value of S
- Case statement allows for a more efficient way to specify:

```
always @(*)
	case (S)
		0: f=W[0];
		1: f=W[1];
		2: f=W[2];
		3: f=W[3];
	endcase
```

### Another case example

- Concatenation operator dynamically creates a 3-bit variable
- Default case can be used to catch all other cases

```
module dec2to4(W, En, Y);
	input [1:0] W;
	input En;
	output reg [0:3] Y;

	always @(W, En)
		case({En, W})
			3'b100: Y = 4'b1000;
			3'b101: Y = 4'b0100;
			3'b110: Y = 4'b0010;
			3'b111: Y = 4'b0001;
			default: Y = 4'b0000;
		endcase;

endmodule
```

- Remember: the curly braces represent concatenation (which means that the case argument is actually a 3-bit number)

### More on case statements

- Previous case statement could have been written

```
if(En==1 & W==2'b00) Y = 4'b1000;
else if(En==1 & W==2'b01) Y = 4'b0100;
else if(En==1 & W==2'b10) Y = 4'b0010;
else if(En==1 & W==2;b11) Y = 4'b0001;
else Y = 4'b0000;
```

- If all possible cases not listed, need default

### One more example

- The ALU we looked at had two mux'ing circuits:
	- selective inversion for operand B
	- selection for the final result to be either the output of the adder or a true/false indication
- How to implement these as case statements, using the 2-bit command as the selection quantity?
	- In place of F1,F0, let's use Command[1:0]

### Example usage of case

- If specifying ALU in Verilog, Result could be set in a case statement

```
Always @(*)
	case(Command)
		2'b00: Result = Sum;
		2'b01: Result = Sum;
		2'b11: Result = {0,0,0,LT};
		default: Result = Sum;
	endcase
```

---

## Modeling a flip-flop

- Use edge of clock in sensitivity list
	- Models the snapshot behavior of a flop
	- No reason to execute the code except for when there's a rising edge

```
module flipflop(D, Clock, Q);
	input D, Clock;
	output reg Q;

	always @(posedge Clock)
		Q = D;

endmodule
```

- `posedge` is a keyword in Verilog
	- We use it in the above example to say that our flip-flop is a positive edge trigger

---

## The subtlety of non-blocking assignments

### Multiple flops in the same block

- Because always block is evaluated sequentially, need to make sure behavior is as intended
	- Both Q1 and Q2 would get D in this example

```
module example5_3(D, Clock, Q1, Q2);
	input D, Clock;
	output reg Q1, Q2;

	always @(posedge Clock)
	begin
		Q1 = D;
		Q2 = Q1;
	end

endmodule
```

![diagram](16.1.png)

### Non-blocking statements

- Forces simulator to update in parallel
- Generally used when modeling flops
	- Doesn't make a difference in simple designs
	- Multiple interacting synchronous modules

```
module example5_4(D, Clock, Q1, Q2);
	input D, Clock;
	output reg Q1, Q2;

	always @(posedge Clock)
	begin
		Q1 <= D;
		Q2 <= Q1;
	end

endmodule
```

![diagram](16.2.png)

- `<=` is the non-blocking statement
	- It looks like at less than or equal to sign, but it is supposed to represent more of an arrow to the left
	- Purpose is to use over `=` in the above example because it assigns to `Q2` the value of `Q1` before it was set to the value of `D` (non-sequential) (as opposed to setting `Q2` to the value of `Q1` after it was set to the value of `D`)
	- Good practice to use

---

## Modeling a register, with load enable

### Modeling registers

- Registers are just multi-bit flip-flops
	- Buses for inputs and outputs
- Load enables control updates
	- But not in sensitivity list, just posedge clock

```
Module fourBitReg(D, clock, En, Q);
	input [3:0] D;
	input En, clock;
	Output reg [3:0] Q;

	Always @(posedge clock)
		if(En) Q = D;

Endmodule
```

---

## Separating combinational logic from state updates

### A note about usage of always

- There are multiple ways to specify sequential circuits in Verilog
- For our sanity, we will use two always blocks to avoid confusion
	- One for combinational logic (`always @(*)`)
		- Causes simulator to evaluate whenever an input changes
	- One for flip-flops (`always @(posedge clk)`)
		- Causes simulator to only evaluate at the clock edge, since that's the only time the output can change

### Verilog for sequential circuits

- Combinational logic generates "next" value as a function of "current" value
- Flip-flops update "current" value with "next"

![diagram](16.3.png)

---

[Counters ->](17.md)