diff options
-rw-r--r-- | 14.md | 4 | ||||
-rw-r--r-- | 15.1.png | bin | 0 -> 621 bytes | |||
-rw-r--r-- | 15.10.png | bin | 0 -> 25464 bytes | |||
-rw-r--r-- | 15.11.png | bin | 0 -> 7024 bytes | |||
-rw-r--r-- | 15.2.png | bin | 0 -> 2255 bytes | |||
-rw-r--r-- | 15.3.png | bin | 0 -> 10483 bytes | |||
-rw-r--r-- | 15.4.png | bin | 0 -> 9164 bytes | |||
-rw-r--r-- | 15.5.png | bin | 0 -> 3185 bytes | |||
-rw-r--r-- | 15.6.png | bin | 0 -> 12437 bytes | |||
-rw-r--r-- | 15.7.png | bin | 0 -> 15649 bytes | |||
-rw-r--r-- | 15.8.png | bin | 0 -> 8519 bytes | |||
-rw-r--r-- | 15.9.png | bin | 0 -> 8471 bytes | |||
-rw-r--r-- | 15.md | 140 | ||||
-rw-r--r-- | 16.1.png | bin | 0 -> 6582 bytes | |||
-rw-r--r-- | 16.2.png | bin | 0 -> 6354 bytes | |||
-rw-r--r-- | 16.3.png | bin | 0 -> 23343 bytes | |||
-rw-r--r-- | 16.md | 343 |
17 files changed, 487 insertions, 0 deletions
@@ -84,3 +84,7 @@ ![circuit](14.9.png) ![truth table](14.10.png) ![graphical symbol](14.11.png) + +--- + +[Datapath concepts: buses, registers, multi-bit muxes, shift registers ->](15.md) diff --git a/15.1.png b/15.1.png Binary files differnew file mode 100644 index 0000000..a54f9e3 --- /dev/null +++ b/15.1.png diff --git a/15.10.png b/15.10.png Binary files differnew file mode 100644 index 0000000..4b28353 --- /dev/null +++ b/15.10.png diff --git a/15.11.png b/15.11.png Binary files differnew file mode 100644 index 0000000..e0d1b5d --- /dev/null +++ b/15.11.png diff --git a/15.2.png b/15.2.png Binary files differnew file mode 100644 index 0000000..e1a05b8 --- /dev/null +++ b/15.2.png diff --git a/15.3.png b/15.3.png Binary files differnew file mode 100644 index 0000000..3760c1d --- /dev/null +++ b/15.3.png diff --git a/15.4.png b/15.4.png Binary files differnew file mode 100644 index 0000000..63a3e7d --- /dev/null +++ b/15.4.png diff --git a/15.5.png b/15.5.png Binary files differnew file mode 100644 index 0000000..5684282 --- /dev/null +++ b/15.5.png diff --git a/15.6.png b/15.6.png Binary files differnew file mode 100644 index 0000000..c43bdcc --- /dev/null +++ b/15.6.png diff --git a/15.7.png b/15.7.png Binary files differnew file mode 100644 index 0000000..5686552 --- /dev/null +++ b/15.7.png diff --git a/15.8.png b/15.8.png Binary files differnew file mode 100644 index 0000000..ae5c861 --- /dev/null +++ b/15.8.png diff --git a/15.9.png b/15.9.png Binary files differnew file mode 100644 index 0000000..3994167 --- /dev/null +++ b/15.9.png @@ -0,0 +1,140 @@ +[\<- Sequential design basics](14.md) + +--- + +# Datapath concepts: buses, registers, multi-bit muxes, shift registers + +## Buses and registers + +### Datapath elements + +- Before we get into more sequential design, taking a detour to learn some concepts/abstractions/terminology associated with multi-bit values + - Buses + - Registers + - Multi-bit muxes +- Also a good time to learn some more Verilog before returning to sequential design + +### What is a bus? + +- A set of wires generally treated as a single entity +- Often expressed/labeled like an array of wires + - E.g., data[31:0] + - Range from 31 to 0 (encompasses 32 values) + - Represents a bus called data that has 32 individual bits/values (32 bit bus) + - Each index denotes a different wire +- Schematic notation uses a slash and a number to indicate bus "width" + - The below diagram represents a 4 bit bus + +![diagram](15.1.png) + +### Registers + +- A group of flip-flops used to store the individual bits of some multi-bit value + - E.g., a 32-bit register is a group of 32 flip-flops, with each flop holding one of the 32 bits +- Schematic representation is a flip-flop with buses connected to the input and output + - Bus width implies the number of flip-flops + +![diagram](15.2.png) + +--- + +## Load enables + +- There is \*always\* a value on the D input of a register; wires always have a value + - There may be times when it is undesirable for that value to be captured in the register +- If a bus connects to a number of registers, you want to control which one loads data + - `E` is the load enable input in the diagram below + +![using a multiplexer](15.3.png) +![clock gating](15.4.png) + +### Register w/load enable + +- Previous pictures intended to show concept in detail, i.e., how it works +- Abstraction just uses E to represent load enable capability + - The muxing or clock gating is implied +- This 8-bit register just needs to show one enable (E) + +![diagram](15.5.png) + +### Load enable usage example + +- ALU takes two input operands to generate a result +- What if we just had one bus to get the operands to the ALU? + - Use registers to hold the operands + - Use load enables to control when the value on the bus is loaded into which register +- Maybe the result gets captured in a register, but only if the answer is correct + - Another use of the load enable concept + +### Block diagram w/load enables + +- Datapath with controls + +![diagram](15.6.png) + +--- + +## Multi-bit muxes + +- We've seen buses, which are actually multiple wires +- We've seen registers, which are multiple flip-flops +- Multiplexers are also often multi-bit + - Drawn as a single instance in a schematic + - Bused data inputs and outputs imply multiple instances + - Select signals still a function of the number of choices, \*not\* the width of the data buses + +### 8-bit wide 4:1 mux + +![diagram](15.7.png) + +--- + +## Shift register concept + +- A special type of register that chains the flip-flops together so that bits can move position +- Uses: + - multiplying/dividing by 2 + - a type of counter + - tracking the position of an object + - serial \<-> parallel conversion + +### Basic Shift Register + +![circuit](15.8.png) +![a sample sequence](15.9.png) + +### Loadable shift register + +- Can either shift right, or load a set of 4 bits at one time + - Parallel inputs: D3, D2, D1, D0 + +![diagram](15.10.png) + +--- + +## Universal shift register + +### Other shift register functions + +- Previous example had "shift right" and "load" functions +- Other functions could be "shift left" and "hold" + - hold = don't change anything +- A universal shift register (USR) provides all four functions + - What would this look like? + +### One bit of the USR + +- Assuming 2-bit encodings in the table + +|S1S0|function | +|----|-------- | +|00 |Shift left | +|01 |Shift right| +|10 |load | +|11 |hold | + +![diagram](15.11.png) + +--- + +[Procedural Verilog and specifying sequential circuits in Verilog ->](16.md) diff --git a/16.1.png b/16.1.png Binary files differnew file mode 100644 index 0000000..0d74b6c --- /dev/null +++ b/16.1.png diff --git a/16.2.png b/16.2.png Binary files differnew file mode 100644 index 0000000..66cc250 --- /dev/null +++ b/16.2.png diff --git a/16.3.png b/16.3.png Binary files differnew file mode 100644 index 0000000..b71e0f2 --- /dev/null +++ b/16.3.png @@ -0,0 +1,343 @@ +[\<- 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) |