summaryrefslogtreecommitdiff
path: root/16.md
diff options
context:
space:
mode:
Diffstat (limited to '16.md')
-rw-r--r--16.md343
1 files changed, 343 insertions, 0 deletions
diff --git a/16.md b/16.md
new file mode 100644
index 0000000..bf4b602
--- /dev/null
+++ b/16.md
@@ -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)