Compare commits
28 Commits
8dae88fc8c
...
ff4330471b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ff4330471b | ||
![]() |
08065a130b | ||
![]() |
9c785ecdb9 | ||
![]() |
b81328a442 | ||
![]() |
0154999092 | ||
![]() |
df32788c07 | ||
![]() |
e985b57ae4 | ||
![]() |
3b4bb73264 | ||
![]() |
b4c30e79ef | ||
![]() |
2456b82189 | ||
![]() |
1e688a3614 | ||
![]() |
70f2be9fcb | ||
![]() |
32186127e2 | ||
![]() |
116ab612fc | ||
![]() |
ba1c7d92b6 | ||
![]() |
8d046bb2a6 | ||
![]() |
dd8478dd48 | ||
![]() |
0295402131 | ||
![]() |
400c362f17 | ||
![]() |
d54cecc801 | ||
![]() |
d697cba7ba | ||
![]() |
ab2da117b9 | ||
![]() |
4aec1d9883 | ||
![]() |
ec2dec1d5e | ||
![]() |
d66a6f21a8 | ||
![]() |
26c966e0bd | ||
![]() |
3e31d38873 | ||
![]() |
d1713efdab |
3
.obsidian/core-plugins.json
vendored
3
.obsidian/core-plugins.json
vendored
@ -27,5 +27,6 @@
|
|||||||
"sync": false,
|
"sync": false,
|
||||||
"canvas": true,
|
"canvas": true,
|
||||||
"bookmarks": true,
|
"bookmarks": true,
|
||||||
"properties": true
|
"properties": true,
|
||||||
|
"webviewer": false
|
||||||
}
|
}
|
@ -1,3 +1,9 @@
|
|||||||
|
# Half Adder
|
||||||
|
|
||||||
|
# Full Adder
|
||||||
|
|
||||||
|
# Ripple Carry Adder
|
||||||
|
|
||||||
# Carry-Select Adder
|
# Carry-Select Adder
|
||||||
A carry select adder is built using two ripple carry adders, and multiplexing them together based off of the value of $c_{in}$. This is done for performance reasons, because when adding two numbers $x$ and $y$, we know $x$ and $y$ *before* we know the value of $c_{in}$. This means we can compute what the output of $x + y + c_{in}$ would be for $c_{in} = 0$ and $c_{in} = 1$ at the same time, then just toggle between the two possible values given the *actual* value of $c_{in}$.
|
A carry select adder is built using two ripple carry adders, and multiplexing them together based off of the value of $c_{in}$. This is done for performance reasons, because when adding two numbers $x$ and $y$, we know $x$ and $y$ *before* we know the value of $c_{in}$. This means we can compute what the output of $x + y + c_{in}$ would be for $c_{in} = 0$ and $c_{in} = 1$ at the same time, then just toggle between the two possible values given the *actual* value of $c_{in}$.
|
||||||
|
|
||||||
@ -5,3 +11,5 @@ The delay is calculated like so:
|
|||||||
1. Given the delay of a full adder is $k$, and the delay of a 2 to 1 mux is $\frac{1}{m}k$,
|
1. Given the delay of a full adder is $k$, and the delay of a 2 to 1 mux is $\frac{1}{m}k$,
|
||||||
2. then the delay of a 4 bit ripple carry adder is $4k$, because it's 4 full adders chained together, running sequentially.
|
2. then the delay of a 4 bit ripple carry adder is $4k$, because it's 4 full adders chained together, running sequentially.
|
||||||
3. This means that the delay of a 4 bit carry select adder is $4k + \frac{k}{m}$
|
3. This means that the delay of a 4 bit carry select adder is $4k + \frac{k}{m}$
|
||||||
|
|
||||||
|
# Carry-lookahead adder
|
@ -0,0 +1,41 @@
|
|||||||
|
# Feb 3, 2025 | ECE2700; HW 2 | Boehme, James
|
||||||
|
---
|
||||||
|
# 1.
|
||||||
|
## Problem Statement:
|
||||||
|
> Describe in Verilog, a full adder that accepts the following three one bit inputs: $x$, $y$, and the carry-in bit $c$; and it generates the following two one-bit outputs: the sum bit $sum$ and the carry-out bit $cout$.
|
||||||
|
|
||||||
|
> **Part a)** For the first full-adder design, describe the $sum$ output using *structural* verilog, and the carry-out output $cout$ using behavioral verilog.
|
||||||
|
|
||||||
|
> **Part B)** Describe the second full-adder design using *hierarchical* Verilog. Describe the half-adder module first using *behavioral Verilog*. Then instantiate two half adders in your full adder.
|
||||||
|
|
||||||
|
> **Part C)** Create a Verilog testbench for the complete full-adder circuit. Make sure your testbench provides all input combinations for your full adder module.
|
||||||
|
|
||||||
|
## Given
|
||||||
|
The logic expressions
|
||||||
|
$$ sum = \bar{x}y\bar{c}_i + x\bar{y}\bar{c}_i +\bar{x}\bar{y}\bar{c}_i + xyc_i $$
|
||||||
|
$$ cout = xy + xc_i + yc_i $$
|
||||||
|
## Find
|
||||||
|
|
||||||
|
---
|
||||||
|
# <u>Solution:</u>
|
||||||
|
## a)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## b)
|
||||||
|
|
||||||
|
---
|
||||||
|
## c)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
---
|
||||||
|
# 2.
|
||||||
|
## Problem Statement
|
||||||
|
|
||||||
|
## Given
|
||||||
|
## Find
|
||||||
|
---
|
||||||
|
# <u>Solution</u>
|
||||||
|
---
|
||||||
|
---
|
135
education/computer engineering/ECE2700/Verilog/Modules.md
Normal file
135
education/computer engineering/ECE2700/Verilog/Modules.md
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
Modules are the building block through which Verilog is built.
|
||||||
|
|
||||||
|
Each module can be thought of as a black box with a series of inputs, and a series of outputs. Changing the input changes the outputs.
|
||||||
|
|
||||||
|
Module definitions are started with the `module` keyword, and closed with the `endmodule` keyword.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
The general syntax of a module is as follows:
|
||||||
|
```verilog
|
||||||
|
// This line is referred to as the *module header*
|
||||||
|
module <name> ([port_list]);
|
||||||
|
// Contents of the module
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// The port list is optional
|
||||||
|
module <name>;
|
||||||
|
// Contents
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
|
||||||
|
Below is an example of the structure of a half adder module:
|
||||||
|
```verilog
|
||||||
|
module half_adder(
|
||||||
|
input a,
|
||||||
|
input b,
|
||||||
|
output sum_bit,
|
||||||
|
output carry_bit
|
||||||
|
);
|
||||||
|
// ------- snip ------------
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ports
|
||||||
|
Ports are a set of signals that act as input and outputs for a particular module.
|
||||||
|
|
||||||
|
There are 3 kinds of ports:
|
||||||
|
- `input`: Input ports can only receive values from the outside. `input` ports cannot be written to.
|
||||||
|
- `output`: Output ports can be written to, but not read from.
|
||||||
|
- `inout`: Inout ports can send *and* receive values.
|
||||||
|
|
||||||
|
Ports can be declared in the port list, or in the module body. Ports declared in the port list can optionally omit their type and only declare a name, to be specified within the body of the module:
|
||||||
|
```verilog
|
||||||
|
module half_adder(
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
sum_bit,
|
||||||
|
carry_bit
|
||||||
|
);
|
||||||
|
input a;
|
||||||
|
input b;
|
||||||
|
output sum_bit;
|
||||||
|
output carry_bit;
|
||||||
|
// ----------- snip -----------
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
|
||||||
|
The full type of a port can also be defined within the portlist:
|
||||||
|
```verilog
|
||||||
|
```verilog
|
||||||
|
module half_adder(
|
||||||
|
input wire a,
|
||||||
|
input wire b,
|
||||||
|
output wire sum_bit,
|
||||||
|
output wire carry_bit
|
||||||
|
);
|
||||||
|
input a;
|
||||||
|
input b;
|
||||||
|
output sum_bit;
|
||||||
|
output carry_bit;
|
||||||
|
// ----------- snip -----------
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port types
|
||||||
|
If no type is defined, ports are implicitly defined as *nets* of type `wire`.
|
||||||
|
|
||||||
|
> In verilog, the term *net* refers to network, and it refers to a connection that joins two or more devices together.
|
||||||
|
|
||||||
|
Ports can be a vector type:
|
||||||
|
```verilog
|
||||||
|
module test(a, b, c);
|
||||||
|
input [7:0] a;
|
||||||
|
input [7:0] b;
|
||||||
|
output [7:0] c;
|
||||||
|
// -------- snip ---------
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
|
||||||
|
# Instantiation
|
||||||
|
Larger designs can be built by using multiple smaller modules.
|
||||||
|
|
||||||
|
Modules can be *instantiated* within other modules and ports, and these *instances* can be connected with other signals.
|
||||||
|
|
||||||
|
These port connections can be defined by an *ordered list*, or by *name*.
|
||||||
|
|
||||||
|
### By Ordered List
|
||||||
|
```verilog
|
||||||
|
module submodule (input x, y, z, output o);
|
||||||
|
// ------- snip -------
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module parent;
|
||||||
|
wire a, b, c;
|
||||||
|
wire o;
|
||||||
|
// Similar to C, the type of the module is first, followed by
|
||||||
|
// the name of the module instance.
|
||||||
|
submodule foo (a, b, c, o);
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
|
||||||
|
### By Name
|
||||||
|
Ports can also be joined by explicitly defining the name.
|
||||||
|
|
||||||
|
Syntactically, this is done with a dot (`.`), followed by the port name defined by the design, followed by the signal name to connect, wrapped in parenthesis (`.x(a)`).
|
||||||
|
```verilog
|
||||||
|
module submodule (input x, y, z, output o);
|
||||||
|
// ------------snip-----------------
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module parent;
|
||||||
|
wire a, b, c;
|
||||||
|
wire o;
|
||||||
|
submodule foo (
|
||||||
|
.x(a),
|
||||||
|
.y(b),
|
||||||
|
.z(c),
|
||||||
|
.o(o)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Because association is done by name, the order of definition does not matter.
|
||||||
|
|
||||||
|
### Unconnected ports
|
||||||
|
Ports that are not connected to any wire by the parent module will have a value of high impedance, and is considered unknown/undefined.
|
||||||
|
|
88
education/computer engineering/ECE2700/Verilog/Types.md
Normal file
88
education/computer engineering/ECE2700/Verilog/Types.md
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
There are two main categories of data types in Verilog. These categories differ in the underlying hardware structure they represent, and they differ in the way they are assigned and retain values.
|
||||||
|
# Nets
|
||||||
|
A *net* refers to a *network* of connections that join two or more devices together.
|
||||||
|
|
||||||
|
Nets connect different hardware entities and *do not store values*.
|
||||||
|
## Wire
|
||||||
|
A `wire` is the most commonly used type of net. When a port is declared in Verilog, it is implicitly given a type of `wire`.
|
||||||
|
|
||||||
|
It is illegal to re-declare a name already in use by a net:
|
||||||
|
```verilog
|
||||||
|
module foo;
|
||||||
|
wire abc;
|
||||||
|
wire a;
|
||||||
|
wire b;
|
||||||
|
wire c;
|
||||||
|
|
||||||
|
wire abc; // ILLEGAL: The wire `abc` is already defined
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
A variable is a data storage element. They retain the last input given.
|
||||||
|
```verilog
|
||||||
|
```verilog
|
||||||
|
module testbench;
|
||||||
|
integer int_a; // Integer variable
|
||||||
|
real real_b; // Real variable
|
||||||
|
time time_c; // Time variable
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
int_a = 32'hfacd_1b34; // Assign an integer value
|
||||||
|
real_b = 0.1234567; // Assign a floating point value
|
||||||
|
|
||||||
|
#20; // Advance simulation time by 20 units
|
||||||
|
time_c = $time; // Assign current simulation time
|
||||||
|
|
||||||
|
// Now print all variables using $display system task
|
||||||
|
$display ("int_a = 0x%0h", int_a);
|
||||||
|
$display ("real_b = %0.5f", real_b);
|
||||||
|
$display ("time_c = %0t", time_c);
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
```
|
||||||
|
```
|
||||||
|
## Registers
|
||||||
|
A `reg` can be used to model hardware registers because it stores a value until the next assignment.
|
||||||
|
|
||||||
|
### Integer
|
||||||
|
A Verilog `integer` type is a 32 bit wide storage value. It does not *need* to store integers, it can be used for other purposes.
|
||||||
|
```verilog
|
||||||
|
integer count;
|
||||||
|
```
|
||||||
|
### Time
|
||||||
|
A `time` variable is unsigned, 64 bits wide, and can be used to store time duration for debugging purposes. `realtime` is similar, but time is stored as a floating bit value.
|
||||||
|
|
||||||
|
## Real
|
||||||
|
The `real` type denotes a floating point value.
|
||||||
|
|
||||||
|
## Strings
|
||||||
|
Strings are stored in a vector of `reg`s. The width of the `reg` *must* be large enough to hold the string.
|
||||||
|
|
||||||
|
Each character in a string represents a one byte ASCII value. If the size of the variable is smaller than the string, the string is truncated.
|
||||||
|
# Scalar and Vector Types
|
||||||
|
By default, declarations of a net or `reg` value is 1 bit wide, referred to as a *scalar* value (only a single value).
|
||||||
|
|
||||||
|
```verilog
|
||||||
|
// Scalar declaration
|
||||||
|
wire foo;
|
||||||
|
// Vector declaration, with 8 bits.
|
||||||
|
wire [7:0] bar;
|
||||||
|
```
|
||||||
|
|
||||||
|
Individual bits in a vector can be accessed using array operators, eg `[i]`.
|
||||||
|
|
||||||
|
```verilog
|
||||||
|
reg [7:0] foo;
|
||||||
|
|
||||||
|
// Write to bit 0
|
||||||
|
foo [0] = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Part selects
|
||||||
|
A range of contiguous bits from within another vector can be selected, referred to as a part select. This range can then be treated as a vector.
|
||||||
|
```verilog
|
||||||
|
reg [31:0] foo;
|
||||||
|
// Select bits 23 through 16 (inclusive), and assign the 8 bit hex value `0xff` to them.
|
||||||
|
foo [23:16] = 8'hff;
|
||||||
|
```
|
@ -17,8 +17,11 @@
|
|||||||
- Put in public domain in 1990
|
- Put in public domain in 1990
|
||||||
- Standardized in 1995
|
- Standardized in 1995
|
||||||
- Originally intended for simulation of logic networks, later adapted to synthesis
|
- Originally intended for simulation of logic networks, later adapted to synthesis
|
||||||
|
- Structural Verilog describes how things are laid out at a logic level.
|
||||||
|
|
||||||
- Behavioral Verilog describes broader behavior, at a higher level
|
## Structural Verilog
|
||||||
|
Structural Verilog describes things at a logic level.
|
||||||
|
- The use of logic gates and continuous assignment are markers of structural Verilog.
|
||||||
```verilog
|
```verilog
|
||||||
// V---V---v--v-----portlist (not ordered)
|
// V---V---v--v-----portlist (not ordered)
|
||||||
module example1(x1, x2, s, f);
|
module example1(x1, x2, s, f);
|
||||||
@ -32,24 +35,24 @@ module example1(x1, x2, s, f);
|
|||||||
and(g, k, x1);
|
and(g, k, x1);
|
||||||
and(h, s, x2);
|
and(h, s, x2);
|
||||||
or(f, g, h);
|
or(f, g, h);
|
||||||
|
// You can also do this
|
||||||
|
assign f = (~s & x1) | (s & x2);
|
||||||
endmodule
|
endmodule
|
||||||
```
|
```
|
||||||
|
## Behavioral Verilog
|
||||||
|
Behavioral Verilog describes broader behavior, at a higher level
|
||||||
|
- The use of `reg`s, time delays, arithmetic expressions, procedural assignment, and other control flow constructs are markers of behavioral Verilog.
|
||||||
```verilog
|
```verilog
|
||||||
// V---V---v--v-----portlist (not ordered)
|
// V---V---v--v-----portlist (not ordered)
|
||||||
module example1(x1, x2, s, f);
|
module example1(x1, x2, s, f);
|
||||||
// Defining the types of the various ports
|
// Defining the types of the various ports
|
||||||
input x1, x2, s;
|
input x1, x2, s;
|
||||||
output f;
|
output f;
|
||||||
// You can also do this
|
|
||||||
assign f = (~s & x1) | (s & x2);
|
|
||||||
// Or this
|
|
||||||
always @(a, b)
|
always @(a, b)
|
||||||
// always @(....) says "do this stuff whenever any of the values inside of @(...) change"
|
// always @(....) says "do this stuff whenever any of the values inside of @(...) change"
|
||||||
{s1, s0} = a + b;
|
{s1, s0} = a + b;
|
||||||
endmodule
|
endmodule
|
||||||
```
|
```
|
||||||
- Structural Verilog describes how things are laid out at a logic level
|
|
||||||
|
|
||||||
## Testbench Layout
|
## Testbench Layout
|
||||||
- Define UUT module
|
- Define UUT module
|
@ -14,6 +14,12 @@ If we have the coordinate pair $(a, f(a))$, and the value $h$ is the distance be
|
|||||||
- The slope of the *tangent line* or the *instantaneous velocity* can be found by taking the limit of the above function as the distance ($h$) approaches zero:
|
- The slope of the *tangent line* or the *instantaneous velocity* can be found by taking the limit of the above function as the distance ($h$) approaches zero:
|
||||||
$$\lim_{h \to 0}\dfrac{f(a + h) - f(a)}{h}$$
|
$$\lim_{h \to 0}\dfrac{f(a + h) - f(a)}{h}$$
|
||||||
The above formula can be used to find the *derivative*. This may also be referred to as the *instantaneous velocity*, or the *instantaneous rate of change*.
|
The above formula can be used to find the *derivative*. This may also be referred to as the *instantaneous velocity*, or the *instantaneous rate of change*.
|
||||||
|
|
||||||
|
# Point Slope Formula (Review)
|
||||||
|
$$ y - y_1 = m(x-x_1) $$
|
||||||
|
Given that $m = f'(a)$ and that $(x_1, y_1) = (a, f(a))$, you get the equation:
|
||||||
|
$$ y - f(a) = f'(a)(x - a) $$
|
||||||
|
|
||||||
# Line Types
|
# Line Types
|
||||||
## Secant Line
|
## Secant Line
|
||||||
A **Secant Line** connects two points on a graph.
|
A **Secant Line** connects two points on a graph.
|
||||||
@ -37,6 +43,15 @@ Given the equation $y = f(x)$, the following are all notations used to represent
|
|||||||
# Higher Order Derivatives
|
# Higher Order Derivatives
|
||||||
- Take the derivative of a derivative
|
- Take the derivative of a derivative
|
||||||
|
|
||||||
|
# Constant Rule
|
||||||
|
The derivative of a constant is always zero.
|
||||||
|
$$ \dfrac{d}{dx}[c] = 0$$
|
||||||
|
For example, the derivative of the equation $f(x) = 3$ is $0$.
|
||||||
|
# Derivative of $x$
|
||||||
|
The derivative of $x$ is one.
|
||||||
|
|
||||||
|
For example, the derivative of the equation $f(x) = x$ is $1$, and the derivative of the equation $f(x) = 3x$ is $3$.
|
||||||
|
|
||||||
# Exponential Derivative Formula
|
# Exponential Derivative Formula
|
||||||
Using the definition of a derivative to determine the derivative of $f(x) = x^n$, where $n$ is any natural number.
|
Using the definition of a derivative to determine the derivative of $f(x) = x^n$, where $n$ is any natural number.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user