ECE 526 Digital Integrated Circuit Design with Verilog and

ECE 526
Digital Integrated Circuit
Design with Verilog and
SystemVerilog
Laboratory Manual
Department of Electrical and Computer Engineering
California State University, Northridge
Fall 2014
CONTENTS
1. Documentation Guidelines ……………………………………………………
3
2. Testing Digital Logic………………………………………………………….. 12
3. Lab 1. Familiarization with Synopsys VCS ………………………………….
18
4. Lab 2. Structural Modeling of a Master-Slave Flip-Flop …………………….
27
5. Lab 3. Hierarchical Modeling ……………………………………………….
29
6. Lab 4. Behavioral Modeling of a 5-bit Counter ……………………………...
32
7. Lab 5. Scalable Multiplex……………………………………………………… 34
8. Lab 6. Carry Select Adder ……………………………………………………. 36
9. Lab 7. Register File Modeling …………………………………………………. 39
10. Lab 8. Arithmetic-Logic Unit Modeling………………………………………. 43
11. Lab 9. Modeling a Sequence Controller………………………………………. 45
12. Lab 10. Final Project: The RISC-Y CPU…………………………………….
52
13. Appendix A Unix Command Reference Guide …………….………………... 57
14. Appendix B vi Editor Command Reference Guide …………………………… 61
2
Documentation Guidelines
Laboratory Reports
All laboratory reports will have a cover page with the students’ names, the class, the
problem number and the problem title prominently displayed.
All lab reports must include printouts of graphical waveforms showing simulation results
and log files of the simulations done. Resolve any errors or warnings before submitting a
lab report. Submitted log files may not contain warning or error messages. All text,
code and waveforms are to be computer printed without edits. You may copy the file
into a word processor adding page breaks, titles and page numbers but nothing more.
While these computer-generated outputs and all source code must be included in a lab
report, they are supporting documentation, not the body of the lab report. The essential
elements of a lab report are:
– A statement of what you are accomplishing, demonstrating, determining,
etc.
– Methodology: statement of how you did it. Specifically include a test plan.
Include flow charts and other materials as appropriate.
– Analysis of results: what did you demonstrate/prove.
– Conclusions.
Any lab report without the above elements will be incomplete and will be graded
accordingly.
Academic Dishonesty
Submitting any report that is not entirely your own work is a form of academic
dishonesty and will not be tolerated. Each and every lab report must include the
following statement, signed and dated by the student. Lab reports without the statement
will be summarily rejected.
I hereby attest that this lab report is entirely my own work. I have not copied either
code or text from anyone, nor have I allowed or will I allow anyone to copy my
work.
Name (printed)
_______________________________
Name (signed)
_______________________________ Date _________________
3
Documentation
This is a course about hardware development using a hardware description language. The
application may be modeling hardware but the method is coding of language constructs.
As such, documentation of your circuit descriptions will be a key part of the grading.
All modules should be clearly written and well documented.
The purpose of documentation is to identify the code and to explain both the “what” and
the “why” of the code. In school, documentation is also where you demonstrate your
understanding of class material. Part of learning the skill of documentation is knowing
what is important and what is trivial. Do not document the trivial. Over the course of the
class, what is new and important in the early problems may become trivial later on.
Each module should have a header that identifies it and its author(s). An example is:
/***************************************************************************
***
***
*** EE 526 L Experiment #1
Student_Name, Spring, 2003 ***
***
***
*** Experiment #1 title
***
***
***
***************************************************************************
*** Filename: Filename.v
Created by Student_Name, Date ***
***
--- revision history, if any, goes here --***
***************************************************************************/
Module headers must give the filename, the author(s) and the experiment number.
You will write and debug modules without documenting each change. But once
submitted, further changes should be noted. There will be such cases: a clock module,
used with one problem, then modified and used with another problem. That second use
may require several changes but only the overall change should be documented.
Normal practice, whether for this course or in professional engineering environments, is
to put each module in a separate file, although it is perfectly legal to combine modules in
one file. Whether separate or combined, each module must have a module header that
describes it.
Module Purpose
After the header, document the purpose of the module if it’s not obvious. A module that
models hardware should describe what it models and anything special or important about
how the modeling is done. A module that tests another module or modules (called a
testbench) should document what it tests and what its test strategy is.
4
Test Plan
A test plan is a high-level description or “executive summary” of the tests performed by
the module. It is not an exhaustive list of all the tests being performed. Every lab report
must include a test plan documenting what tests are to be performed and explaining why
they are adequate for the device under test. For most labs, an exhaustive test strategy is
impractical, so some thought will have to be put into devising an adequate yet nonexhaustive test plan. It is extremely unlikely that a test plan that does not cause every
circuit output to change states at least once will be satisfactory.
An example test strategy for testing an 8-input MUX might be:
“Test strategy: Test A-path (all ones, all zeros and alternate bits), B-path, undefined and
hi-z select, example undefined and hi-z on A- and B-path inputs.”
An example test strategy for testing an adder might be:
“Test strategy: Apply all 0 and 1 cases, with and without carry-in to test carry
propagation (or no-carry propagation); apply alternate 1-0 and 0-1 cases (each cell adds
without carry-out); apply alternate 1-0 and 0-1 cases (each cell adds with carry-out); add
max positive and max negative with and without carry-in to test for arithmetic overflow.”
An alternate test strategy for the adder might be:
“Test strategy: Generate exhaustive test of all combinations of X- and Y-inputs and
carry-in.”
When the purpose of a test is not obvious, add a parenthetical comment explaining what
is being tested (e.g. carry propagation).
Model Documentation
Where different modeling approaches are possible, explain your choice. For example,
there are different ways of assigning values to variables and they have subtle differences
in their operation. Your documentation should indicate your understanding of the
differences and why the chosen construct is the correct choice for this particular model.
Any of the following cases require explanation (and this is not an exhaustive list!):
1. Use of an intra-assignment delay.
2. Use of a non-blocking assignment.
3. Use of a clocking construct (posedge or negedge) with a signal other than a
clock or reset.
4. Use of a wait delay.
5. Use of a procedural continuous assignment with a signal other than a reset or
preset.
6. Use of multiple procedural continuous assignment statements with a single
signal.
7. Handling of exception conditions such as simultaneously active read and write
strobes or arithmetic overflow.
5
In industry, there is a strong bias for reusing modules. This requires that each module
document any limitations or unusual behavior. This applies in the lab, too. If your model
is incomplete in some fashion, whether by hardware limitation or abbreviated coding you
must identify the limitations that flow from that incompleteness. For example, an adder
module may have no signal to indicate arithmetic overflow. You must document this in
your module.
Modeling Style
Modules have different sections and different functions. Especially for the first few
problems, you should identify each section of each module: port or signal declarations,
netlists, module instantiations, signal display, test stimuli, etc. In all cases, you should
use a blank line or two to separate sections. When modeling sequential logic, it’s usually
a good idea to model synchronous and asynchronous functions separately.
// Describe the asynchronous behavior
code
// reset is active low
// Describe the synchronous behavior
code
// clock is positive edge triggering
Use indentation to indicate the level or importance of each line of code. Indentation
improves the look of the code, organizes it and because delimiters should pair at the same
level of indentation it aids in troubleshooting.
A TAB indents too far so use three or four spaces for each level of indentation. All code
between the module and endmodule keywords is subordinate to the module and should
be indented one level. Code outside the module (typically `timescale or `define) is at the
same indentation level as the module keyword.
Some constructs have subordinate clauses or subprocesses. These should be indented
below the superior process. For example:
initial
initialization_action;
if (test_clause)
action_if_test_is_true;
// indented one level below keyword
// indented one level below keyword
Other constructs serve to delimit sections of code. The most common is the begin…end
keyword pair. Others include fork… join and case… endcase. All code within these
delimiters should be indented one level below the delimiter. The delimiters themselves
may also be indented as shown in the following examples:
6
case ({sel1, sel0})
0: action_for_selection_zero
1: action_for_selection_one
2: action_for_selection_two
3: action_for_selection_three
default: action_for_undefined_selections
endcase
if (test_clause)
begin
true_action_one;
true_action_two;
end
else
begin
false_action_one;
false_action_two;
end
Lines that are too long to fit comfortably on a page, i.e. longer than about 75 or 80
characters, can be broken anywhere there is whitespace, typically right after a comma.
The rightmost part of the line is indented at its proper level. The remaining part or parts
of the line are indented one more level.
Strings are an exception to the “break the line at whitespace” rule. Strings cannot
continue on a second line. They must be broken into two separate strings, each on its
own line and (usually) separated by a comma. Strings can, however, be broken anywhere
except between the backslash and following character of so-called escaped characters.
“A long string cannot be broken somewhere in the middle and continued
on another line.”
“But a long string can be broken into two strings, one on one line, a comma,”,
“ and the other on the following line.”
Very occasionally (in this class, at least), a statement is both long and deeply indented.
Breaking such a line according to the usual procedure results in many short, choppy lines
that are difficult to read. In such cases, outdent or move up (left) in indentation levels so
that more of the statement can appear on each line. As a rule of thumb, outdent at least
two levels. Of course the outdent is used only for the extremely long statements and
should not be continued with later statements.
module
o
o
o
7
begin
Short_statement_isn’t_outdented
Extremely_long_statement_deeply
indented_and_broken
according_to_usual
procedure_resulting_in
many_short_and_choppy
lines
Extremely_long_statement_deeply_indented_then_outdented
So_more_of_the_statement_appears_on_each_line_thus
Making_the_statement_easier_to_read
Another_extremely_long_statement_deeply_indented_then_outdented
so_more_of_the_statement_appears_on_each_line
Short_statement_isn’t_outdented
Short_statement_isn’t_outdented
Short_statement_isn’t_outdented
end
o
endmodule
o
o
Commonly the $monitor and $display statements, while not deeply indented, will still
extend far beyond the right margin of the page. These statements can be broken
anywhere there is a comma (except within a string):
$display (“----Time---- ----Address---- ----Data ---- Rd Wr ALE M/IO”,
“ s0 s1 NMI TxD RxD”);
$monitor ($time, %hAdr %hData %b %b %b %b “,
”%b %b %b %b %b”, MemAddr, MemDat, Read_Not, Write_Not, ALE, Mem_IO, Status0, Status1,
NMI, TxData, RxData);
The printout generated by a monitor or display statement may also be longer than a
printable line. Such lines can be compacted or indented with the “\n” and “\t” constructs,
signifying newline and tab, respectively.
For all submitted printouts, all lines must fit. Any lines exceeding the printable width
(and therefore not available for review) will be penalized. It is the student’s
responsibility to ensure that the full text of any line is printed.
Verilog allows variable names to be essentially unlimited in length. It is therefore
advisable to assign descriptive variable names wherever possible (clock, select, data_in,
etc.). On the other hand, someone must type these long variable names and every
additional character increases the chance of a typo, so some restraint is necessary. One
exception is loop indices where single letters, typically i, j, k, etc. are common and well
understood.
8
How to Lose Points
As the semester progresses, inefficient or unnecessary code will be penalized since it
shows a lack of understanding of how Verilog works and since it violates the sine qua
non of engineering: elegance of design.
Strive for an aesthetically pleasing appearance as well as for completeness and technical
accuracy.
Example of a poorly written module:
module mux2(x,y,s,e,z);
output z;
input x, y, s, e;
always @ (x or y or s or e) if (e) z = 1’bz; else z = s?y:x;
endmodule
9
Example of a well written (and documented) module:
/***************************************************************************
***
***
*** EE 526 L Experiment #1
Student_Name, Spring, 2003 ***
***
***
*** Experiment #1 title
Group # group_number ***
***
***
***************************************************************************
*** Filename: Filename.v
Created by Student_Name, Date ***
***
--- revision history, if any, goes here --***
***************************************************************************
*** This module models a 2:1 mux with active low enable:
***
***
Enable
Select
Mux_Out
***
***
1
don’t care
Hi-Z
***
***
0
1
B_Input
***
***
0
0
A_Input
***
***
0
undefined
A_Input
***
*** The undefined Enable case is not modeled. Module treats undefined ***
*** Enable as if it were zero (enabled).
***
***************************************************************************/
module mux2(A_Input,
B_Input,
Select,
Enable,
Mux_Out);
//
//
//
//
//
LS mux input
MS mux input
Select signal (see truth table above)
Mux enable, active low
Mux output
// Declare the inputs and outputs
output Mux_Out;
input A_Input, B_Input, Select, Enable;
// Declare signal type
wire Mux_Out, A_Input, B_Input, Select, Enable;
// Model the mux
always @ (A_Input or B_Input or Select or Enable)
if (Enable)
Mux_Out = 1’bz;
// disabled case
else
if (Select)
Mux_Out = B_Input;
else
Mux_Out = A_Input;
endmodule
10
Testing and Verification of Digital Logic
The purpose of testing is to develop confidence that a design or its specific
implementation is functioning correctly or to identify the location and nature of the
fault(s) within it. Since the numbers, types and locations of possible faults are
astronomical, no amount of testing can guarantee a perfect design. Fortunately, many
different faults will exhibit the same symptoms meaning that one test will detect them all.
Also, some faults are more likely than others so a test for the most common faults will
yield high confidence (but not certainty) in the perfection of the design. The nature and
extent of testing depends, in part, on the assumptions about the design and the
information desired from the test. For example, a board built from a known good design
and implemented with tested parts may be presumed correct after just a few functional
tests while an unproven design may require extensive testing to achieve similar
confidence.
The three major types of digital logic tests are:
 Functional: does the design work?
 Characterization: are design parameters within specification?
 Troubleshooting: where are the faults? Can they be fixed?
Each type of test needs a different set of test vectors. A functional test of an
adder, for example, probably concentrates on the LSB, the MSB and the sign bits with
less concern for the middle bits of the adder. A troubleshooting test concentrates on each
bit or logic pathway without regard for how it functions or how it interacts with other
bits. A characterization test concentrates on extreme conditions such as all ones and all
zeros and the parametric events during transitions between them, and on propagation time
from LSB to MSB and sign. A functional test might provide a partial characterization or
troubleshooting test but seldom a complete one; and similarly for the other two types.
Faults are usually classified as:
 Stuck-at faults where a node is stuck-at-one, stuck-at-zero, or stuck open.
 Bridging faults where two or more signal lines are shorted together.
 Parametric faults where one or more design parameters are outside their
specifications.
 Design faults where the individual logic elements operate correctly but the
ensemble, the design, does not function as intended.
Because Verilog modeling is an idealization of the logic elements, most
ECE 526L testing will be directed at finding design flaws. This flaw occur when the
student misunderstands the design requirements, incorrectly encodes a correctly
understood requirement through typing errors or misapplication of the modeling
constructs; or ignores or improperly accounts for anomalous, illegal or exception
conditions. (Note that Verilog can be made to model stuck-at faults and can model
specific technologies for parametric testing).
11
FUNDAMENTALS OF TESTING
To be detected, a fault condition must yield a different output than the fault-free
design for at least one test pattern of the test suite. Every signal line should exhibit both
logic states during the test. (This is a necessary but not a sufficient condition for testing
that signal.) A test suite designed to detect single stuck-at faults will also detect a high
percentage of multiple faults including bridging faults. Not all faults are testable due to
redundancy in the design. (Redundancy means non-minimal logic but may be necessary
for hazard elimination or for fault tolerance). Because it focuses on the individual nodes
and signal paths in a design, stuck-at fault testing is not particularly effective at testing
algorithms and functions. (Remember that the individual logic elements will probably all
function correctly in a circuit with design faults).
TEST STRATEGIES

Exhaustive test: apply all combinations of logic states to the inputs (usually as a
binary counting sequence). Easy to create. Detects all detectable faults. Works only
on combinational logic (but with correct signal segregation and control, can
sometimes be used with sequential logic). Test time doubles for each added input.
High degree of redundancy in the test suite for all but the smallest circuits and
redundancy increases with number of inputs. A divide and conquer strategy can cut
test time by limiting testing to independent blocks of logic.

Random test: apply random combinations of values to the inputs. A reasonable
number of random test vectors will detect a high percentage of all detectable faults.
“Reasonable” may range from 10–50% of the number of exhaustive test vectors.
Suffers from the same problems as an exhaustive test. Duplicate test vectors use time
but detect no new faults. (Duplicate test vectors are also hard to find). No guarantee
that any particular fault will be detected.

Heuristic test: apply limited set of hand-generated test vectors. Human beings can
often identify the most important areas to be tested. Is not systematic or algorithmic.
Often the method of choice for functional testing. Fault detection or “fault coverage”
depends on the skill of the test designer.

Algorithmic test: use an algorithm or procedure such as the D-Algorithm, PODEM, or
FAN or algebraic methods such as Boolean difference to create test patterns.
Creating programs to generate the test vectors is hard but once created, test generation
is easy. May not find all detectable faults. May not generate the most efficient test
suite. May be the only way to generate an acceptable test suite in a reasonable period
of time for large designs.
12
COMBINATIONAL VS. SEQUENTIAL TESTING
Logic gates
Outputs
Inputs
Combinational circuits have no elements (flip-flops, latches, memories, registers
or other structures) that hold a value. Sequential circuits do contain such elements.
Therefore, the tester can directly control all inputs to a combinational circuit for each test
vector but lacks such direct control with a sequential circuit. Each test vector applied to a
combinational circuit is independent of all other test vectors. Scrambling the test vectors
changes only the order of discovery of faults. Test vectors applied to a sequential circuit,
however, are not independent because they affect the memory elements of the circuit –
and these are part of the test inputs for subsequent test vectors. In cases where the
memory elements are themselves sequential such as shift registers and state machines,
setting the desired pattern into the memory elements may require considerable effort and
test time.
Inputs
Outputs
Generalized Combinatorial Circuit
Logic gates
Clock
Reset
Memory
Elements
Generalized Sequential Circuit
Figure 1. The difference between combinational and sequential circuits
Sequential circuit testing usually follows this general pattern: inputs are initialized
and an asynchronous reset is applied (and removed) to initialize the memory elements,
then various test vectors are applied to the inputs in synchronism with (but not
necessarily coincident with) one edge of the clock while outputs are sampled and
memory elements are updated on one edge of the clock, usually the same edge as the
inputs for high speed circuits and usually the opposite edge for low speed circuits.
Depending on the needs of the test, the asynchronous reset may be applied more than
once. The clocking signal may be symmetric or not, may have a fixed or variable
frequency and may be syncopated with stretched, shortened or missing pulses during part
of the test.
13
FUNCTIONAL TESTING AND VERIFICATION
Functional verification, the primary testing ECE 526L students will do, must adhere to
the fundamental tenet of testing: a fault, if present, must yield a different output than the
fault-free case. As an example, consider a 2-input multiplexer. If zeros are applied to
both inputs, then it is impossible to tell which input is actually selected. A non-zero
output does indicate a fault, but if the intent was to test the selection circuit, a zero output
is null, i.e. it gives no information. To be detected, an incorrect function must yield a
different output than the correct function for at least one test pattern of the test suite.
Suppose the student sets one input of the MUX to zero, the other to one, and then
toggles the select between states. Upon observing the output toggling with the select, the
student concludes the model is correct… but is it? With only one state applied to either
input, the output is indistinguishable from just the select (or perhaps from select ). To
detect an incorrect control function, inputs must be toggled between states for each
combination of control states. To illustrate the point further, consider a 4-input MUX. It
has four control states and so requires a minimum of 8 tests (2 input states for each of the
four control states) to fully verify the select function. (This also indicates how redundant
an exhaustive test would be: four inputs and two controls would require 26 = 64 tests).
Now imagine an 8-wide array of 2-input multiplexers. If the byte on input A is
8’h00 and the byte on input B is 8’hFF, then the inputs are distinguishable and the basic
tenet is met. But what if, through mischance, the order of inputs on B is reversed. Here’s
another undistinguished fault. To make that fault distinguishable, additional trials with
8’h0F, 8’h33, and 8’hAA may be required (they’re not the only possible patterns to
distinguish this fault).
Generally, design errors reverse the ordering of a full group of signals, one set of
data inputs or an entire data bus, for example, and not just a sub-group within it –
provided the design does not build up the group from smaller elements or subdivide the
group into separate functions. Whenever signals are grouped (e.g. data[15:0] ) use
opposite states for LSB and MSB to detect reversals of desired bit ordering. Whenever
grouped signals are built up by concatenation, also test for correct bit and sub-group
ordering. Suppose, for example, that a 9-bit control bus, ctrl, is created from a 3-bit
opcode, a 2-bit mode, a direction bit (input or output) and a 3-bit address. The desired
control bus is
[O O O M M D A A A]
control bus
8 7 6 5 4 3 2 1 0
bit numbering
with the opcode in the high order bits and the other signals in order below it. To
guarantee a correct control bus, the order of the sub-groups must be verified. That is, are
the opcode bits in positions 8 to 6, mode bits in positions 5 and 4, and so forth. Further,
is the opcode MSB in position 8, the mode MSB in position 5, and so forth.
Generally when a group of signals is subdivided with part selects, problems occur
not in the module that subdivides the group but in other modules that use the sub-group.
Testing must ensure that the sub-group ordering in module A is respected by module B.
14
Test vectors that find many faults are said to be “robust.” Test time is valuable
and the less of it used, the better – provided, of course, that the necessary faults are
checked. Recall the statement that stuck-at fault testing was not particularly good at
verifying functionality. True, but if functional test vectors are written so that stuck-at
testing can also be done, the vectors are probably quite robust. Students will be
expected to write robust test vectors, i.e. to minimize the number of test vectors while
maximizing the number of faults checked.













Typical questions to ask (although not all questions apply to every problem):
Are different inputs distinguishable by different patterns?
Can reversed bit ordering be detected (especially across module boundaries)?
Can shorts between adjacent bus signals be detected?
Do the asynchronous functions work: does SET make a low output go high and a
RESET make a high output go low? Does ENABLE work? Does a tri-state
ENABLE work?
Do the synchronous functions work: do outputs change only on the right clock edge?
Do the asynchronous functions override the synchronous functions?
Is the state table or transition table verified with the given test suite? Have unused
states been checked?
Is the control table or are the control functions verified with the given test suite?
Have data inputs been toggled for every combination of control states? Have unused
combinations or states been checked?
Are anomalous, illegal or exception conditions tested and does the circuit conform to
specification or at least do something reasonable. Does the model generate a warning
message for illegal inputs?
Have all inputs and outputs and as many internal signal lines as possible been
switched between logic states?
Have undefined (‘bx) and high impedance (‘bz) states been applied to critical inputs?
Have the input and output extremes been tested (largest, smallest, positive, negative,
leftmost, rightmost, etc.)
Has the test suite been documented to indicate what is tested, assumptions made, and
tests omitted (if any)?
COURSE REQUIREMENTS AND CAUTION
Testbenches must include a test strategy and must, as a minimum, ensure that all signals
to and from the module(s) under test change state at least once during the test. Testing
should show an understanding of the functions being tested. An exhaustive
combinational pattern should not be blindly applied to sequential logic, for example.
Signals should not be undefined, floating, or un-initialized. Violations will be penalized.
Behavioral Coding Style and Errors
Most labs will be written in behavioral Verilog/SystemVerilog, though the first ones will
use structural modeling. In behavioral code, there are several techniques that may
15
simulate correctly but would either fail to produce any hardware at all or produce
defective hardware when synthesized. These stylistic errors are easy to avoid. While the
list below is not exhaustive in that there is an infinite variety of ways to produced
defective designs, by following these guidelines many common errors can be avoided.
1. Always have an “else” clause for every “if.”
2. Have a default clause for every case statement.
3. If one signal in a sensitivity list is edge sensitive, all must be.
4. Avoid all use of combinational feedback. Sequential feedback is fine.
5. Avoid all use of continuous assignments for anything other than bidirectional
port interfaces.
6. Do not put explicit time delays into circuit descriptions. Their use is limited to
non-synthesizable test fixtures.
7. Clock and reset signals are always primary inputs.
8. While there are sometimes valid reasons for violating synchronous design
guidelines, none of them apply to the labs in this manual. Synchronous design is
mandatory for all designs in this course.
9. Never split assignments to any one variable between “always” blocks.
10. Use only one assignment operator (blocking or non-blocking) for any
operand.
Some of the above rules are likely to seem esoteric and incomprehensible at the start
of the semester. Refer back to this list as the semester progresses and you learn
more about behavioral hardware description.
16
Experiment # 1
Familiarization with Linux and the Synopsys VCS Simulator
Note that there frequently is more than one way to accomplish a task in Linux. As you
develop proficiency with this operating system, you may find procedures that will work
as well as or better than the ones specified here.
Log into any of the workstations in the laboratory by entering your account number and
user password. Once you logged into the system, a graphical user interface will start. To
access lab tools you need to open a terminal window. The Terminal window accepts
Linux OS commands, which are summarized in Appendix A. Open a terminal window by
right mouse clicking on the empty desktop space to bring up the Workspace menu and
selecting Open Terminal with a left click. This will give you a terminal window as shown
below. The window may be resized with the mouse.
Figure 1. Terminal Window on the Desktop
Enter following UNIX commands to create a folder called “lab1” and change directory
down into it:
 mkdir 526
 cd 526
 mkdir lab1
 cd lab1
17
A structural description of a 2-input MUX using Verilog built-in gate-level primitives is
shown in Figure 2 below. Using a text editor, enter the model and store it in a file in
directory “lab1”. The workstations have several text editors available, including the
venerable vi, an extended version of vi, vim (for vi, improved), emacs and others. The
operating system also includes a text editor called gedit, which is available from the
Applications Accessories  Text Editor menu in the top left of the screen.
Appendix B of this manual has a list of useful vi commands. Many tutorials for vi and
other editors are freely available on the web. There are also commercial books going into
great detail on their use and capabilities. Use of a word processor such as Microsoft Word
may result in invisible control characters being embedded in your code that will prevent
the tools from reading your files.
Using the editor of your choice, enter the design and save it to a file. The module name
and the file name should be consistent. All Verilog files should be saved with a .v
extension. If your file contains SystemVerilog constructs, use a .sv file name extension.
The first labs do not make use of any such advanced features, but later ones will.
The test fixture model for the 2-input MUX is given in Figure 3 below. Using a text
editor, enter the test code and store it in a new file, also in folder “lab1”. Again, the
module name and the file name should be consistent.
Figure 2. Two input MUX Model
18
Figure 3. Two input MUX Test Fixture Model
Compile the two files by entering the command:
vcs –debug MUX2_1.v tb_MUX2_1.v If your source code contains any SystemVerilog constructs, vcs needs to be invoked with
the –sverilog option:
vcs –debug –sverilog file1.sv, file2.sv Next, invoke the simulator by entering the command:
simv Simv does not need any arguments, though it can be instructed to create a log file as
shown below. It will operate on whatever binaries were created by the previous step. The
output of the simulation is shown in Figure 4.
If the two files are typed correctly, you will get no error messages. If you get any error
message then it is your job to debug your code and get it to compile and simulate
correctly.
19
Figure 4: Simulation Results
Running simv will send text-based output to the screen. The $monitor statement in the
test fixture sets which signals are to be displayed. Any signal at any level of hierarchy
may be seen this way. A log file of the simulation run may be created by adding –l
<logfilename> to the simv command, i.e.
simv –l lab1.log The Linux tee operator can also be used to send the simulation output simultaneously to
the terminal window and a log file.
simv | tee lab1.log Text-based simulation is adequate for some projects. However, debugging is often helped
by referencing graphical waveforms. The inclusion of the line “$vcdpluson” in the test
fixture and the invocation of the simulator with the –debug option enabled the graphical
viewer.
To see a waveform of the simulation, first type “dve &” from the terminal window. This
will cause a blank simulation window to pop up, as shown in Figure 5.
20
Figure 5: Wave Viewer Environment
To populate this environment, left mouse click on File and select Open Database. From
the Open Database window, select vcdplus.vpd, as shown in Figure 6. This will cause the
DVE window to show your top level design (the test fixture) in the Hierarchy window
and the unit under test’s primary input and output signals to be displayed in the Variable
window, as shown in Figure 7.
Select all the signals with the mouse, then right click and select “Add to WaveNew
Wave View.” This will cause the view shown in Figure 8 to appear.
21
Figure 6: Selecting the simulation data base for graphical display
22
Figure 7: Waveform viewer with MUX2_1 data base loaded.
23
Figure 8: Simulation waveform showing top-level signals.
Returning to the Hierarchy window on the DVE screen, enable scoping down into the
design by clicking on the + sign next to the test fixture’s name. Click on the lower-level
design and its signals too will appear in the Variable window. These internal signals can
then be added to the waveform.
You can navigate around the waveform, add and remove cursors, zoom in and out, etc.
via the mouse and by selecting menu items from the top of the waveform window. You
can rearrange the order of signals displayed by dragging and dropping them in the
leftmost waveform window. Changing the radix displayed, which can be done from the
leftmost window in DVE, will prove useful in later labs but in this lab, all signals are
single bit, so simple binary is the only option.
Images for this manual were created by moving the mouse into the window to be saved
and, from the keyboard, pressing the “Print Scrn” key while holding down the Alt key.
You can do the same for your lab reports.
Exit from DVE
To exit DVE, select File  Exit from the DVE window. Click OK to confirm the exit.
Note: In any type of graphical UNIX application, always use File  Exit to terminate
the application. Do not simply close the window using the window controls
since that does not guarantee proper return of the license token(s).
24
Test Fixture Module Modification
Modify your test fixture module to exhaustively test the mux module by considering all
possible combinations of all the input signals. For this lab only, this includes X and Z
values. Simulate the design with your new, expanded test fixture.
In future labs, exhaustive testing shall NOT be taken to include X and Z values on inputs.
Analysis
Do the Verilog primitives work the same as real gates would work? Scoping down into
the design under test to see internal nodes may help you determine this. Gate level
analysis of your simulation and Verilog theory is required.
In your report, include your Verilog code, your log files and your DVE waveforms. Note
that these files are supporting documentation for your report, not the report in its entirety.
Additional Question
On pages nine and 10 of this manual, there are two examples of behavioral code for a 2:1
multiplexer. Would you expect them to perform identically both to each other and to the
gate-level design you have used in this lab? Explain your answer. A simple yes or no will
get no credit.
25
Experiment #2, Structural Modeling of a JK Flip-Flop
In this experiment, you will model and test a J K flip-flop. You will incorporate gate
delays and study their effects and you will study the operation of the four Verilog system
tasks for watching signal behavior.
Delay times through integrated circuit gates depend on the capacitive loading of the
output. This is dominated by the physical length of the connection it drives and by the
type of conductor, either polysilicon or metal. In real-world designs, the delays must be
estimated until process flow reaches the Place and Route phase. Estimates often use
device fan-out. Here, we use 300 ps for a fan-out of one, 500 ps for a fan-out of two,
800 ps for a fan-out of three, and 1.5 ns for the fan-out and estimated loading on the
“external” outputs (the Q and Qb signals). Note these are not “external” in the sense of
driving devices off the chip, they merely drive longer conductors “external” to the flipflop itself. Delay values are far longer than current state of the art CMOS processes.
n1
SD
NAND2
NAND4
n2
NAND1
Q
CP
J
a1
n3
Q
AND1
nr
K
NOR1
NAND3
NAND5
a2
AND2
RD
JK_ff.vsd
1. Using primitive gates, write a Verilog module for the J K flip-flop shown above.
In your module,
a. Use the following module header:
module flop(J, Kb, SDb, CP, RDb, Q, Qb);
o
o
o
endmodule
26
b. Assign delays to the gates according to the following:
Gate
Two input gates
Three input gates
Four input gates
Primary Output
Delay
time_delay_1
time_delay_2
time_delay_3
time_delay_4
Time Steps
2
4
6
15
c. Set the timestep to 100 ps using the `timescale compiler directive.
d. To make future changes in time delay easy, use the `define directive to define
time delays time_delay1, time_delay_2, time_delay_3 and time_delay_4.
e. The total delay of a gate is the sum of the intrinsic gate delay (from the table
above) and the fanout delay as specified in the introductory paragraphs.
2. Write a testbench module to verify the functionality of your flip-flop. In this module,
use each of the output system tasks, $monitor, $display, $write and $strobe. Do not
simply display the same data using each task. Instead, take advantage of the
differences between them to show that you understand those differences and can use
them to good effect.
The J K flip-flop you are encoding should function as shown in the table below.
However, using this table as a template to write your vectors will not work correctly,
due to the persistence of X values in Verilog and that indeterminate is not a specific
value.
J
SD
0
1
0
1
1
1
CP
x
x
x
0
1
0
K
x
x
x
0
1
1
x
x
x



RD
1
0
0
1
1
1
1
0
1

1
x
x
1

1
Q
1
0
1-?
0
1
q
q
q
Q
0
1
1-?
1
0
q
q
Mode
Async Set
Async Reset
Indeterminate
Load 0 (reset)
Load 1 (set)
Hold (ncng)
Toggle
Hold (ncng)
q
(x = don’t care,  = positive edge,  = not a positive edge)
The inputs must be stable before the clock edge. You can cause rising edges on the
clock line by first setting it to 0 and then to 1. You should experiment with a
symmetric clock (50% duty cycle) and with a clock that uses only a short positive
pulse.
Be sure to allow sufficient time between input changes for the effects to propagate
through the circuit. This is a sequential circuit and must be tested accordingly. How
fast is too fast for your device? Answer this for both 50% and short cycle clocks.
27
Experiment #3, Hierarchical Modeling
In this experiment, you will model an edge triggered flip-flop using a hierarchical
modeling approach. You will then model and test an 8-bit register using an array of
instances of this flip-flop.
1.
Using primitive gates, write a Verilog module for the SR Latch shown in Figure
1. Use a header similar to the one shown below, but use a suitable timescale for
the delays indicated in point 3.
`timescale 1ns/1ns
module SR_Latch2(Q, Qnot, s0, s1, r0, r1);
output Q, Qnot;
input s0, s1, r0, r1;
o
o
o
endmodule
Save your module in a Verilog file with the same name as the module.
2.
Using the SR_Latch2 module and primitive gates, write a Verilog module for the
positive edge triggered flip-flop shown in Figure 2. Use the following module
header:
module dff(q, qbar, clock, data, clear);
output q, qbar;
input clock, data, clear;
o
o
o
endmodule
Save your module in a suitably-named .v file.
3.
For all your models, use the following delay data:
Single-input gates: intrinsic delay of 2 ns.
Two-input gates: intrinsic delay of 3 ns.
Three-input gates: intrinsic delay of 4 ns.
Capacitive loading of 0.3 ns for a fanout of one.
Capacitive loading of 0.5 ns for a fanout of two.
Capacitive loading of 0.8 ns for a fanout of three.
1.5 ns loading delay for a primary output.
You may assume infinite drive (zero delay) for all primary inputs.
Note that the instances of the SR latch have different delays, depending on where
they are located in the overall design. You must find a solution for setting proper
delays while still using three instances of the original design. There are several
28
ways to make this work. Creating different designs, one for each delay
characteristic, is not an acceptable solution.
4
Write a Verilog model of the 8-bit register with the organization shown in
Figure 3. The register has the logic symbol shown in Figure 4. From its symbol,
the functions of the register’s reset (rst) and enable (ena) can be inferred. Use the
following module header:
module register(r, clock, data, ena, rst);
output [7:0] r;
input [7:0] data;
input clock, ena, rst;
o
o
o
endmodule
5
Write a testbench module, reg_test.v to verify the functionality of your design.
Include stimuli to test the following:
a.
The register resets when rst is zero.
b.
The contents of the data bus are clocked into the register when ena is
asserted.
c.
The contents of the register are preserved and the contents of the data bus
are ignored when the register is clocked with ena deasserted.
6
Incorporate a clock generator with a suitable period for your design in your test
fixture.
7
To reduce typographical errors, put your invocation of the compiler into a force
file. This is a text file that contains all the commands and arguments you would
otherwise have to type in on the command line with each invocation of the
compiler.
For example, if you have design files FileA.sv and FileB.sv and test fixture file
tb_TOP.sv, your force file would consist of
vcs –debug –sverilog FileA.sv FileB.sv tb_TOP.sv
Save the force file in a suitable file time with a .f extension.
By default, Linux files are not executable. Make your force file executable by
typing from the command line
chmod +x <filename>.f
29
Calculate the maximum operating frequency of the entire design. Demonstrate in
your simulation and analyze in your report what happens when you exceed that
frequency. Correlate your calculated and observed maximum frequencies.
s0
SR Latch
Figure 1
Q
s1
Qnot
r1
r0
sbar
cbar
clr
s
clear
q
clkbar
clk
qbar
clock
r
dbar
data
d
rbar
data[0]
r[0]
dff
data[7]
MUX
Positve Edge-Triggered D Flip-Flop with Clear
Figure 2
MUX
8
r[7]
dff
ena
clk
rst
Schematic for 8-bit Register with Clear
Figure 3
data
ena
ena
clk
clk
rst
rst
data[7:0]
register
r[7:0]
Circuit Symbol for Register
Figure 4
reg_out
30
Experiment #4, Behavioral Modeling of a 5-bit Counter
data[4:0]
load
enable
clock
Counter
reset
cnt[4:0]
1. Create a behavioral model of a 5-bit reloadable up counter.
a. Use the following timescale, inputs and outputs:
Single bit inputs CLK, RST, LOAD, ENABLE
Five bit input DATA
Five bit output CNT
1 ns/1ns timescale
Save your file as counter.sv.
b. Model RST as an asynchronous, active low input.
c. Model LOAD as a synchronous, active high input. When asserted, the value on
the data pins is loaded into the counter after the positive edge of the clock.
d. Model ENABLE as a synchronous, active high input. When asserted, the count
is incremented or loaded with new data (if LOAD is high). If ENABLE is not
asserted, the counter will hold its value. The counter does not load new data if it is
not enabled.
e. When LOAD is low, ENABLE is high and RST is high, the counter advances
on the positive edge of the clock.
31
2. Create a module for the asynchronous assert, synchronous de-assert function as
described in class.
3. Integrate the two design modules into a top-level design unit. The AASD circuit should
be at the same level as the counter, not embedded in it.
4. Create a test bench that does the following:
a. Instantiates your top level design.
b. Provides a clock generator with a 10 ns period.
c. Demonstrates an asynchronous reset.
d. Show the counter initiates incrementing after reset is released. After it reaches a
count of 4, parallel load 12 decimal.
e. Demonstrate that it will count from 12 until the counter rolls over (i.e. returns
to zero) and then starts counting back up.
f. Demonstrates that reset overrides both load and increment.
g. Demonstrates the correct functioning of enable.
32
Experiment #5, Scalable Multiplexer
Scalable
Multiplexer
a[size-1:0]
out[size-1:0]
b[size-1:0]
sel
Exp5_aa.vsd
1. Create a Verilog model of a scalable multiplexer, scale_mux.v. Use the following
module header:
`timescale 1ns/1ns
module scale_mux(A, B, SEL, OUT)
o
o
o
endmodule
a. The size of the ports is determined by a parameter, SIZE. If the multiplexer is
not scaled when instantiated, it defaults to one bit wide.
b. Use synthesizable, behavioral Verilog to write the multiplexer module. Note
that there are several ways to code up the design, but you must not do anything
that explicitly or implicitly includes any comparison to x.
c. Your design should function such that input a should be selected when sel = 0
and input b when sel = 1. When sel = x, your multiplexers should resolve any bits
for which a and b are the same. Any bits in conflict should result in x outputs.
2. Create a Verilog testbench to verify that the scalable multiplexer works.
In the test module, create four instances of the scalable multiplexer. Use the three least
significant digits of your student ID that are greater than 1 but not identical and one for
the widths of the multiplexer data paths. For example, if your student ID is 100462983,
you will use 1, 3 and 8 and 9. If your student ID is 54660101, you would use 6, 5, 4 and
1.
Use three different methods of parameter redefinition to change the widths of three of the
instances. Leave the fourth instance with its default width of one bit. i.e. don’t attempt to
set a width. Test each instance to show that all specifications are met. (Note: This is one
testbench with four instances, not four testbenches with one instance each). Drive the
33
largest multiplexer with as many bits as it needs for its a and b inputs. Use as many of the
least significant bits of the a and b buses as needed to drive the smaller instances. The
test vectors for the largest multiplexer should be sufficient to also test the smaller
multiplexers.
NOTE: when testing sel = 1’bx, you must apply a = b and a  b cases and at least one
case where a and b share some common bits and some opposite bits.
Does your model function the same as the gate-level model simulated in Lab 1? Should
it?
34
Experiment #6, Carry Select Adder
The attached circuit diagram represents a 6-bit Carry Select Adder. It is one of the fastest
adder circuits and has much better performance than a regular Ripple Carry Adder. Each
adder stage, with the exception of the first one, consists of two sets of full adders and a
multiplexer circuit. One set of full adders generates the sum and carry bits for the carryin = 0 case and the other generates the sum and carry bits for the carry-in = 1 case.
The carry out of each stage selects the correct sum and carry bits for the following stage.
1. Construct a full adder module using behavioral modeling.
Use a specify block to specify the following delays:
 a or b to sum, 6 ns
 a or b or c_in to c_out, 2 ns
 c_in to sum, 3 ns
2. Construct a 2:1 mux module using behavioral modeling.
Use a specify block to specify the following delays:
 x or y to out, 2 ns
 sel to out, 3 ns
3. Using two pairs of full adder modules and two mux modules, develop a medium-level
module that generates a 2-bit sum. Use supply0 and supply1 nets to implement the
logic 0 and logic 1 carries-in.
4. Using your medium level module, develop the full 6-bit Carry Select Adder module.
Use the following header:
module Carry_Sel_Adder(c6, sum, A, B, c0);
o
o
o
endmodule
5. Write a non-exhaustive testbench to test the functionality of your adder. Select a
small number of robust test vectors. n.b. “small” no more than ten. Your test strategy
should discuss why you chose the particular vectors you did. Why do you think the
chosen set is robust? What, if anything, is not tested by the chosen set?
6. Write an exhaustive testbench to test your adder (including carry-in!) Compare your
adder’s output to the output of a 6-bit behavioral adder (including carry-out!). If they
agree, continue testing until all inputs have been presented. If no errors were found,
indicate the test was successful. If the adders do not agree, indicate the test has failed
and show the operands and the expected and actual outputs. Stop testing when the
first error is found or when all test vectors have been successfully applied.
35
7. To prove your exhaustive testbench will find an error, use a force assignment to
override the behavioral adder’s sum sometime after ¾ of the test vectors have been
applied. Use the `ifdef and `endif compiler directives to include or exclude the code
that forces an error.
In your report, include log printouts from both the error-free and forced error cases. Use
$monitoroff and $monitoron commands to show only the first dozen or so test vectors
(and results) and the last dozen or so for the error free case. For the forced error case, use
them to show the first dozen or so test vectors and about a dozen test vectors before and
including the forced error.
For the error-free case, include SimVision printouts showing the start and end of the test
in sufficient detail to verify the applied signals and how they change. You may, if you
wish, submit one or more “overview” printouts as well.
For the forced error case, include SimVision printouts of the end of the test in sufficient
detail to see when and how the forced error is applied and how the modules react.
To make your output easy to analyze, use decimal numbers and show input values, output
values and expected output values.
36
a5
b5
a4
b4
FA
FA
MUX
FA
b3
1
FA
MUX
a3
b2
FA
FA
0
MUX
a2
MUX
a1
FA
FA
MUX
MUX
s3
s2
b1
a0
b0
1
c2
0
FA
FA
s1
s0
c4
c6
s5
s4
x
MUX
sel
0
1
out
x
y
a
y
sel
carry
out
b
FA =
Full Adder
out
sum
Carry Select Adder
carry
in
c0
Experiment #7, Register File Model
A register file operates similarly to random access memory but is made from flopflops
rather than DRAM or SRAM cells. A register file would consume far more power and take
far more area than a true memory of the same capacity. However, register files have the
advantages of operating fast, faster even than SRAM, and they can easily be coded in any
arbitrary size (width and depth) in Verilog. In this lab, you will create a register file that
will be used as a random access memory.
Use parameters for both width and depth in your model. Where specific sizes are given in
the description below, make those the default values for your parameters.
1. Create a Verilog model of a register file with the following specifications:
a.
b.
c.
d.
e.
f.
g.
h.
i.
The memory has an eight bit bi-directional data bus.
The memory has a five bit address bus.
The output enable (oe) signal is active high.
Chip select (cs) is active low.
The value on the data bus is written to the address on the address bus after the
rising edge of the write strobe (ws).
The contents of the currently specified address are placed on the data bus when
oe is high.
Block read: as long as oe remains high, the contents of the newly specified
address are placed on the data bus.
The data bus returns to the high impedance state after oe goes low.
The chip select signal, cs, must be low to read or write. If it’s high, oe and ws
are ignored and the data bus remains in the high impedance state.
40
Assume the address bus is stable before or at the assertion of oe or ws and remains stable
for at least the access time of the memory. Assume cs will never be changed during a read
or write cycle.
2. Create a Verilog testbench for your memory. It must do the following:
a. write to and read from every memory location.
b. demonstrate both an individual and a block read.
c. demonstrate the specified timings for read and write.
d. test both enabled and disabled memory states.
e. demonstrate that the data bus is in the high impedance state sometime during
the test (typically when oe = ws = cs = low).
f. demonstrate there are 32 locations in the memory (hint: write then read back
and verify a unique value for each address).
g. demonstrate there are no shorts or stuck-at conditions on the data lines. This is
something that is typically done in factory test, not verification, but you can still
write vectors to perform this test.
Note: some of these requirements can be combined in a single test.
41
3. Create a second Verilog testbench that does the following:
a. initializes the memory to the following hex values using the $readmemh
system task:
addresses 5’h04 to 5’h0F: 58 ED B7 34
C9 8F A0 9B
addresses 5’h10 to 5’h17: DA 7E F2 26
86 95 FD B1
65 11 03 4C
addresses 5’h1C to 5’h1E: 12 AF 33
b. demonstrates the memory has been successfully initialized.
c. demonstrates that unspecified locations remain undefined.
d. reads locations 5’h10 to 5’h17, scrambles each byte, and writes the new byte
back into memory. Each original byte is ordered [7654 3210], the new bytes are
ordered [0716 2534]. e.g. 8’hDA becomes 8’h73.
e. demonstrates the memory bytes have been successfully scrambled.
Use a task to print the contents of all memory locations as a 4x8 or 2x16 matrix. To show
parts a through e have been accomplished, invoke the task before and after initialization
and again after scrambling the data bytes. Waveform printouts must be detailed enough to
verify bus timing and content of address and data buses (zoom in until numbers are
readable). Include a printout of your $readmemh data file.
In your report, clearly state how many edge constructs you use in your model and why that
is the best answer for this design.
42
Experiment #8, Arithmetic-Logic Unit Modeling
In this experiment, you will model an arithmetic-logic unit, or ALU.
1. Create a Verilog module of the ALU. Use the following header:
`timescale 1ns/100ps
module alu(ALU_OUT, CF, OF, SF, ZF, OPCODE, A, B, EN, CLK);
parameter WIDTH = 8;
output [WIDTH - 1:0] ALU_OUT;
output CF, OF, SF, ZF;
input [3:0] OPCODE;
input [WIDTH - 1:0] A, B;
input CLK, EN;
o
o
o
endmodule
Save your file as alu.sv.
Use localparams for all the opcodes, but avoid use of any Verilog keywords for any
opcodes. Note that the built-in Boolean primitives do match some of the opcodes and these
names should thus not be used for any localparam names. Remember that while the
simulator is case sensitive, downstream tools may not be.
The ALU will support the instructions listed in Table 1. All opcodes not listed will not
cause any change in ALU outputs.
If the ALU is not enabled (EN is logic 0), all outputs will maintain their previous state.
43
Lab 8 Table 1: Opcodes and Actions
Opcode
Action
4'b0010
A+B
4’b0011
A-B
4’b0100
A and B
4’b0101
A or B
4’b0110
A xor B
4’b0111
not A
The ALU has Overflow, Negative, Zero and Carry flags. These flags are to hold their
values between operations that update them. Overflow and Carry are only updated on
arithmetic (addition or subtraction) operations. Both arithmetic and Boolean operations
will update the other two flags.
Overflow is an indication that a signed operation was too big for the ALU. It is detected by
having the sign bit take an incorrect value. Adding two positive numbers and getting a
negative result would cause the overflow flag to be set, as would adding two negative
numbers and getting a positive sum. Note that since this is a clocked module, the output
and the operands that are used to form the output are never available at the same time.
Getting the overflow flag to operate correctly for subtraction is convoluted if Verilog
subtraction is used. However, if the two’s complement of B is first taken and that is then
added to A, the flag operation is unchanged from that used for addition.
Carry is set when an addition or subtraction results in a carry out of the MSB position.
While the definition for addition carry is clear and universally accepted, that is not the case
for subtraction borrow. In this lab, use the Intel definition, which is that the bit is set for
subtractions where A < B.
The carry flag only has meaning when the operands are considered to be unsigned.
Interpretation of the bit values (signed or unsigned) is up to the user of the computer. This
applies to both the overflow and carry flags as well as to the data output.
The Zero flag is set when the result is all zeros for any ALU operation.
The Negative flag is set when the MSB of the ALU output is logic one. Again, negative is
subject to interpretation by the user. As the hardware designer, you do not know or care
how the operands will be interpreted by a programmer.
Write a test plan to non-exhaustively but thoroughly verify your design.
Implement your test plan in Verilog/SystemVerilog.
Lab report question: should you use signed variables for the data path, that is, for A, B and
ALU_OUT? Some experimentation will be required to adequately answer this question.
44
Experiment #9, Modeling a Sequence Controller
IR_EN
A_EN
Addr[5:0]
B_EN
Opcode[3:0]
PDR_EN
PORT_EN
Phase[2:0]
ALU Flags
Sequence
Controller
I Flag
PORT_RD
PC_EN
PC_LOAD
MAR_EN
ALU_EN
ADDR_SEL
MEM_OE
MEM_CS
Lab 9 Figure 1: Sequencer Inputs and Outputs
A. Creating a Sequence Controller Module
Create a SystemVerilog behavioral module of the sequence controller shown above. Call it
control.sv. Table 4 in this section has a decoding key explaining the meaning of each
output.
Each instruction will take eight clock cycles to complete. A three-bit phase generator
module is included to facilitate decoding of the cycles and associating each cycle with
certain sequencer actions. This simplistic implementation is deliberately inefficient. There
is no technical reason that would prevent some of the actions taken in different cycles from
happening concurrently, shortening the time each instruction takes and increasing
throughput.
When reset is asserted (logic 0), the phase is set to zero, which corresponds to enumerated
type FETCH.
45
The instruction fetched from memory determines which control lines will be asserted
during later cycles. For example, if the operation is a Store, neither Load A nor Load B
will be asserted at any time during the eight cycles, but one of them will be asserted in
cycle three if the operation is a load targeting one of those registers.
Lab 9 Figure 2: Phases
During the Fetch cycle (cycle 0), an address is applied to the program memory. This infers
that the memory must be enabled and in read mode. By the end of the cycle, valid data
should appear at the memory bus. Because this model is written in behavioral code without
any delays, in your simulation, data will appear at the memory outputs instantaneously, but
such ideal performance would never occur in a physical implementation. Hence some time
must be allocated for memory word selection and propagation delays. This is accomplished
by allowing the whole cycle for memory access.
Cycle 1, Latch Instruction, is dedicated to storing the fetched instruction into the
Instruction Register. The sequencer thus must set the IR_EN line high during that cycle.
Leave the memory enabled and in read mode during this cycle.
In Cycle 2, the Instruction Register, which is external to the Sequencer, is decoded and
sends signals to the Sequencer. The Sequencer does not perform any actions during this
cycle. All Sequencer outputs are de-asserted.
46
During the Load Register cycle (Cycle 3), immediate data are latched into one of the
registers according to signals sent from the Instruction Register. Immediate data means that
the data are contained in the instruction, as opposed to being stored in a different memory
location. When data must be fetched from a different memory location, the registers will be
loaded in Cycle 6 rather than Cycle 3. Immediate data are signaled by setting the I Flag.
There are five registers that may be enabled during the Load Register cycle: A and B of the
ALU, the Port Direction Register, the Port Data Register and the Memory Address
Register. The sequencer needs one output for each so that it can enable the appropriate one
during this cycle. The sequencer also needs to control the memory address bus selector,
the memory output enable and the memory chip select.
If the opcode is an ALU operation, the ALU will be enabled in Cycle 4 (EXECUTE cycle).
Cycle 5 is used for setting up memory access in Load and Store operations. In both cases,
the memory address bus must be switched to use the address from the Memory Address
Register rather than the Program Counter.
In Cycle 6, ALU output data or port IO data are written to memory if the operation is a
store. In the case of Load, data from the memory are latched into the selected target
register in this cycle.
In Cycle 7, the Program Counter is updated. The PC is external to the Sequencer but needs
to be enabled by the Sequencer. It can either be incremented or loaded with a new value. It
has two control signals, both set by the Sequencer: Enable and Load. Enable will always be
activated in Cycle 7. Load will only be activated if a Branch or Jump is to be performed.
This is determined by decoding both the opcode and the four ALU flags. If the opcode is
Jump, Load will be activated. If it is BZ, it will be activated only if the Z flag is set. If it is
BN, it will be activated only if the N flag is set, etc.
Each instruction will have the following format:
Bits
31 : 28
27
26 : 21
20 : 8
7:0
Lab 9 Table 1: Instruction Format
Field Meaning
Opcode
Immediate flag: if set, bits 7:0 are immediate data.
Load/Store Address
Reserved
Immediate data
Table 1 is for reference only in this lab. For this lab, the various fields are already broken
out as inputs to the sequencer as needed. The data field is not used in this lab.
Note that although there are Load and Store opcodes as well as Load and Store phase
states, they are not the same thing. There is no direct correlation between them. It would be
47
illegal to use one as a localparam and one as a typedef in the same scope anywhere in the
design.
Clock
Reset
Ph1
X
Ph2
X
Ph3
X
Lab 9 Figure 3: Phase Generator Signals. Use Enumerated Types for the eight states.
Memory mapping
The RISC processor for which this is the controller will be memory mapped as shown in
Table 2. This means that in addition to the 32-deep combined program and data memory,
some machine registers and the I/O port will also be enabled for reading and writing when
addressed. Enabling memory mapped devices requires reading the address bus along with
the opcode. When addressing a memory-mapped register, the main memory should be
disabled.
Lab 9 Table 2: Memory Map
Decimal Address
Device
0-31
Memory
32
ALU A Register
33
ALU B Register
34
Port Direction Register
35
I/O Port
36
Memory Address Register
Any address not covered by the above table is not implemented. Reading from an
unimplemented address will produce unpredictable results. Writing to an unimplemented
address will have no effect.
Note that I/O Port read and write share the same address. Setting the enables is
distinguished by the opcode: when LOAD, data are written to the Port Data Register.
When STORE, the I/O Port drives data onto the bidirectional memory bus. To avoid
contention, the memory output must be disabled when the port is driving, though the
memory chip select must remain active so that new data may be written to the memory.
The instruction set for the CPU is shown in Table 3 below. Any opcode not covered shall
be illegal. You do not need to do anything in hardware to detect illegal input conditions.
48
Lab 9 Table 3: Instruction Set
MNEMONIC INSTRUCTION
LOAD
Load a register
STORE
Store ALU Output
ADD
Add A and B
SUB
Subtract B from A
AND
Bitwise AND of A and B
OR
Bitwise OR of A and B
XOR
Bitwise XOR of A and B
NOT
Bitwise inversion of A
B
Unconditional Branch
BZ
Branch if Z flag is set
BN
Branch if N flag is set
BV
Branch if OVF flag is set
BC
Branch if C flag is set
OPCODE
4'b0000
4’b0001
4’b0010
4’b0011
4’b0100
4’b0101
4’b0110
4’b0111
4’b1000
4’b1001
4’b1010
4’b1011
4’b1100
Lab 9 Table 4: Sequencer Output Key
Pin Name
Function
IR_EN
Enable writing to Instruction Register
A_EN
Enable writing to ALU A register
B_EN
Enable writing to ALU B register
PDR_EN
Enable writing to Port Direction Register
PORT_EN
Enable writing to Port Data Register
PORT_RD
Enable reading Port Input Data
PC_EN
Enable updating Program Counter Register
PC_LOAD
Enable parallel load of PC. Only works if PC_EN is also active
MAR_EN
Enable writing to memory address register for data load/store
ADDR_SEL
Switch memory address bus from PC to memory address register
MEM_OE
Memory output enable. High for memory read, low for write
MEM_CS*
Memory Chip Select: necessary for any memory access, read or write
*MEM_CS (Memory Chip Select) is active low. All other enable signals are active high.
No matter how the module is coded, the inferred circuit must be totally synchronous,
other than the asynchronous assertion of reset. This means that each and every
flipflop in the design receives the same phase of the master clock, which is clk in the
diagrams. This requirement may appear be at variance with diagrams and other text
in this document. These synchronous design rules apply equally to Experiment 10.
There is no one correct way to code the sequencer. It can be done as a classic state
machine. An equally correct design can be made as a series of conditional statements. Your
goal is to produce an elegant, easy to understand and easy to maintain design. While
minimal coding length is not in and of itself a goal, excessively long and convoluted code
is definitely undesirable.
49
B. Creating the Clock Generator
The clock is a primary input from the outside world. Slower periodic signals are derived
from it in a Phase Generator block, which must be reset using an asynchronous assert,
synchronous de-assert reset signal.
Create a SystemVerilog behavioral module of the phase generator shown below
(phaser.sv). Use the following module header:
module phaser(CLK, RST, EN, PHASE);
o
o
o
endmodule
PHASE is a three-bit output using enumerated types {FETCH, LATCH, DECODE,
LOAD, EXECUTE, SWITCH, STORE, INCREMENT}. The three bits of the output must
toggle as shown in the various illustrations, though they will be encoded together to form
the eight enumerated types. Do not make eight outputs. Only three are needed. Only use
SV methods for changing values of the phase.
The enumerated type must be carried through to the top level and the sequencer.
enable
clk
phase
generator
Phase
[2:0]
reset
Exp9_ea.vsd
Lab 9 Figure 4: Phase Generator
The phase generator produces timing signals as shown in the timing diagrams. It must be
synchronous, using only the rising edge of the clock and the falling edge or reset to trigger
output changes. There are several ways in which it can be coded but however it is done, it
must not use any logic signal as a clock.
C. Top level
Combine the design modules into one top level design. Instantiate only the top level design
in your test fixture.
D. Testing with a Stimulus File
Using a similar approach to the one used in Experiment #6, create an automated testbench
to test all modules together. This test fixture must check all outputs and report that the
50
simulation either completed correctly or failed. Use force and release to inject errors and
demonstrate that your test fixture is capable of detecting faulty operation.
Use name declaration (dot naming) to connect signals between the testbench and the
modules under test. List signals in reverse order from their original order in the module
port list. Previously we have used positional declarations.
Both your controller module and your testbench should be well documented. In particular
since the testbench is automated, be sure you document your test strategy.
51
Experiment #10, Final Project: The RISC-Y CPU
During the semester, you have modeled and simulated the following modules:
1.
2.
3.
4.
5.
6.
Scaleable MUX (Lab #5),
8-bit Register (Lab #3),
5-bit Counter (Lab #4),
Scalable RAM (Lab #7),
8-bit ALU (Lab #8),
Sequence Controller (Lab #9), and Phase Generator (Lab #9)
These modules can be put together to form the following RISC-Y CPU system. However,
instead of instantiating the register from Lab 3, you will model several registers of
appropriate sizes behaviorally.
The RISC-Y processor is typical of modern Reduced Instruction Set Computer
architectures such as the ARM family of processors used in virtually all smart phones in
that it has a small, regular instruction set and a load-store architecture. Though it is far
simpler and more stripped down than any current-production machine, it is a complete
microprocessor and could be programmed to accomplish any general purpose computing
task.
Each RISC-Y instruction will use the following format:
Lab 10 Figure 1: Instruction Format
Bits [7:0] are immediate data. When the opcode is Load and the I bit (Bit 27) is set, these
data are loaded into the target register indicated by the Address field (Bits [26:21]). If the I
bit is not set, then the Data field contains the address of the data to be loaded into the target
register. Since this implementation of the RISC-Y CPU only has 32 memory words, only
the least significant bits of the Data field are used for the address pointer. These bits are
loaded into the Memory Address Register for Load and Store operations other than Load
Immediate.
Note that the Address field needs six bits because the CPU has memory-mapped registers,
but five bits are all that are needed for memory addressing.
The RISC-Y CPU has only two addressing modes: Immediate and Direct. Immediate data
are held in the Data field of the instruction. Direct data has the address of the data in the
Data field. They are distinguished by the I bit. When the I bit is set, the addressing mode is
Immediate. Otherwise, it is Direct.
52
There are only two possible objects that may be stored: the ALU output and the port. When
the opcode is STORE, the Address field is checked to see if it contains 35, which is the
address of the port. If there is a match, port data are stored in the address indicated by the
least significant bits of the Data field. For any other address, the ALU contents are stored.
ALU opcodes (ADD, SUB, AND, OR, XOR and NOT) do not need to reference any fields
other than the opcode. They always use the A and/or B registers for operands and the result
always goes to the ALU results register.
The remaining opcodes are all branches. For these operations, the branch address will be
contained in the lowest five address bits. These bits are loaded into the Program Counter.
The major component groups of the RISC-Y CPU are shown in Figures 2 through 4 below.
Lab 10 Fig. 2: RISC-Y Memory Subsystem
53
In addition to the blocks shown in these diagrams, the sequencer and its associated phase
generator from Experiment 9 need to be instantiated and connected. Use the enumerated
type created in Experiment 9. Do not convert it to plain binary.
Lab 10 Fig. 3: IO Subsystem
Lab 10 Fig. 4: ALU Subsystem
54
A. Creating a Verilog module for the RISC-Y CPU:
1. Create a Verilog module for the RISC-Y CPU (cpu.sv). Use the following module
header:
`timescale 1ns/1ns
module cpu (CLK, RST, IO);
input CLK, RST;
inout [7:0] IO;
o o o
endmodule
2. The RISC-Y CPU unit has the following specifications:

A Sequence Controller steps the CPU through a fetch instruction/fetch operand
cycle. This sequence requires eight master clock cycles.

The memory will be 32 bits wide and 32 words deep, or 32 x 32.

The design is to be totally synchronous. The only clock is the master clock. No
derived signals may ever be used as a clock.

While it would be logically correct to use the primitive operator register design
from lab 3, that function should be re-designed using behavioral code. The
behavioral code should not have any delays specified.

The system shall use an asynchronous assert, synchronous de-assert reset. A
module implementing this function must be incorporated into the design.

A Program Counter points to the next location in memory from which the CPU will
fetch instructions or data. The PC is the counter from Lab 4. It may be loaded with
branch addresses or incremented to go on to the next address in sequence.

The ALU only receives operands from the A and B registers, which are eight bits
apiece.

There is one eight-bit input-output port. When it is an output, data can be written to
it by executing a LOAD operation with the ports address (35) in the address field. It
is read by performing a STORE operation with the store address in the data field
and the port address of 35 in the address field.
55

When an eight bit quantity is loaded or stored, the active bits are always the eight
least significant of the referenced memory location.

The port direction is set by writing to the Port Direction Register, address 34. This
is a one-bit register. To simplify the design, all bits operate together as either input
or output.

Data for the one-bit Data Direction Register will take its data from the least
significant bit of the referenced memory location. It can only be changed via a
LOAD operation. There is no provision for reading this register.

The tristate data bus must never be allowed to float. Exactly one driver must always
be active. This means that some modification to the logic controlling memory read
and write will be necessary to prevent a floating bus.

The CPU can process the following instructions:
Lab 10 Table 1: RISC-Y Instruction Set
MNEMONIC INSTRUCTION
OPCODE
LOAD
Load a register
4'b0000
STORE
Store data in memory*
4’b0001
ADD
Add A and B
4’b0010
SUB
Subtract B from A
4’b0011
AND
Bitwise AND of A and B
4’b0100
OR
Bitwise OR of A and B
4’b0101
XOR
Bitwise XOR of A and B
4’b0110
NOT
Bitwise inversion of A
4’b0111
B
Unconditional Branch
4’b1000
BZ
Branch if Z flag is set
4’b1001
BN
Branch if N flag is set
4’b1010
BV
Branch if OVF flag is set
4’b1011
BC
Branch if C flag is set
4’b1100
*Only the ALU output or data read from the port may be directly stored. Store
always refers to the ALU output unless the address of the port appears in the
address field of the STORE instruction.
56
B. Testing with a Stimulus File:
Create a testbench to verify the RISC-Y CPU module. To accomplish this, write a CPU
program is and load it into the memory using $readmemh. After the system is reset, the
processor should start executing your instructions. If all the components of the system are
working properly, the CPU will:






Fetch an instruction from the RAM memory.
Decode the instruction.
Fetch a data operand from the RAM memory if required by the instruction.
Perform any ALU operations required by the instruction.
Store the result when so instructed.
Repeat the cycle by fetching the next instruction.
All steps should be well documented and the results well presented! All instructions
and conditions should be tested.
Multiple test program files are likely to prove advantageous rather than trying to
demonstrate correct functioning of all instructions in one file.
Remember to zoom in so that submitted waveforms are readable. You may, if you wish,
also submit one or more “zoomed out” overview plots.
57
Appendix A
UNIX Command Reference Guide
58
UNIX Command Reference Guide
Note: Commands for the UNIX operating system are case
sensitive, most of which need to be typed in lower case.
Examples are underlined.
set
HELP COMMANDS
help
An interactive facility for on-line
documentation. Type help general for more
information.
apropos Finds commands that deal with a certain
topic. apropos pascal will display commands
pertaining to pascal.
man
Displays information about a specific
command. man mail will display information
about the mail program. man -k graphics will
display a list of man pages that pertain to graphics.
Note: man -k is the same as apropos.
whatis Displays a short description about the function of
a command. whatis mail will display a short
description of mail.
clear
environment. setenv printer l-phe108 sets your
default printer to be the LPS-40 printer (ASCII
mode) in PHE 108.
Changes or sets variables known as shell
variables. set prompt=MyPrompt: will change the
prompt for your current shell to that particular
string.
Clears the terminal screen.
FILE MANIPULATION COMMANDS
ls
Displays (lists) contents of the current directory.
pwd
Displays the name of your currently active
directory, i.e. where you are in the file system.
cd
Changes to another directory. cd /etc will move
you to the directory named “etc”.
cat
Concatenates (sequentially displays) files.
cat proj1.c will display the file at your terminal.
more
Displays a file at your terminal and pauses at the
bottom of each page. more apple.p will display the
file apple.p.
cp
Copies a file. cp apple.p lemon.p creates a new
file, lemon.p, which is identical to apple.p.
mv
Renames a file. mv apple.p lemon.p will rename
the file apple.p to the new name lemon.p.
chmod Changes the read, write and/or execute
permissions (or modes) of a file.
mkdir
Creates (makes) directories.
rmdir
Deletes (removes) directories.
rm
Deletes (removes) a file. Example: rm apple.p
diff
Displays the differences between two files.
Example: diff apple.p lemon.p
sort
Sorts the lines of a file alphabetically. sort a.list
will sort the lines in a.list into alphabetical order.
col
A post-processing filter that removes special
formatting characters. Useful for displaying man
pages during a Telnet session or on a simple TTY.
Example: man keyword | col -b.
find
Finds all files along a specified path that meet
certain conditions. find $HOME -ctime n finds all
files in your home directory (and any
subdirectories) that were modified in the last n
days. (+ctime n finds files modified n or more days
ago). find $HOME -name ‘filename’ finds all files
in your home directory and any subdirectories
matching the filename pattern. Wildcards can be
used.
fgrep
Searches for files containing lines matching a
text pattern. pattern must be enclosed in single
quotes – it is a text “literal”. fgrep -c ‘keyword’
filename prints a count of the number of lines
containing keyword in the file filename. fgrep -f
matchfile filename1 > filename2 copies all lines in
filename1 that match any line in matchfile into file
filename2. See also grep and egrep.
wc
Counts the number of words and characters in a
file. wc apple.c will display the number of words,
characters and lines in the file apple.c.
GENERAL CONCEPTS
C-key
While holding down the control key
(also marked “Ctrl”), press the key after the dash.
C-c means hold the control key and type “c”.
options Generally, UNIX command options are
specified with a character or character string that
begins with a “-” (dash). In the example man -k
mail, “-k” is an option for the man command.
Many times, the order or placement of options is
significant.
CONTROL CHARACTERS
RET
Carriage Return. It sends a completed
command to the system.
C-c
Aborts (interrupts) the current
command or program.
C-z
Stops or suspends the current process.
C-s
Halts the scrolling of output to the
terminal.
C-q
Continues scrolling.
C-o
Stops (flushes) output from being seen
on the terminal.
C-r
Redisplays the command line.
C-u
Erases the command line.
C-w
Erases the last word on the command
line.
DEL
(Delete key) Deletes a single character from
the end of the command line.
BREAK (Break key) Three BREAKs can disconnect
your terminal from the system in an emergency.
SESSION CONTROL & PRIMARY COMMANDS
passwd Invokes program to change login password. You
are prompted for old and new passwords.
logout Terminates the login session.
exit
Exits the current shell.
ps
(with no options) shows your process.
setenv Changes variables associated with your
59
wc -l apple.c will display only the number of lines
in the file apple.c.
>
PRINTING COMMANDS
lp
Prints a file on the default printer. lp MyFile.ps
will print the MyFile.ps on the default printer. Use
the -d device option to direct output to a specific
device.
lpstat
Displays the lp print queue status.
cancel Cancels print requests made with lp. lp ID will
cancel a specific request. (Use lpstat to get ID).
lpr
Alternate print command on some systems,
similar to lp. Prints a file. lpr test.p will send file
test.p to the printer. Use the -P option to specify a
particular printer.
lpq
Alternate print queue display command on some
systems, similar to lpstat. Displays the print queue
for a particular printer and gives your print request
number.
lprm
Alternate print request cancellation command.
lprm -Px-sa1125 60 will cancel print request
number 60 on printer x-sa1125.
>>
|
tee
script
MAIL
mail
COMPILATION/DEBUGGING COMMANDS
cc
Invokes the C compiler.
f77
Invokes the FORTRAN-77 compiler
pc
Invokes the Pascal compiler
dhx
Invokes the symbolic debugger. You must first
compile your program with the debug option
enabled.
?
h
INFORMATION COMMANDS
date
Displays the current date and time.
finger
Displays all users currently on the system.
chfn
Changes the information shown when someone
issues the finger command.
cal
Displays a calendar of the current month. Use
cal mo yr for a specific month or cal yr for a full
year. (yr may be 1–9999 so all digits must be
given).
t
n
e
d
u
COMMUNICATION COMMANDS
mesg
Allows you to receive or block messages to your
terminal. Options are y and n.
write
Puts you in direct communication with another
user. write user will allow you to communicate
with user. Everything you type will appear on
user’s terminal. To stop communication, press C-d
on a new line.
s
r
m
q
ADVANCED FILE MANIPULATION
and REDIRECTION
<
Redirectes the input of a command to read from a
x
60
specified file. mail user < text.msg will send the
letter contained in text.msg to the user named user.
Redirects the output of a command to a specified
file. If the file does not exist, it is created. If it
already exists, the former contents are destroyed. ls
> dir.log will put the names of the files in your
directory in the file dir.log.
Like the > (redirect output) command except data
is appended to an existing file rather than
destroying the original contents.
(Pipe). Connects the output of one command to
the input of another. ls | mail user will send a
listing of the names of your files to user.
Like the pipe (above) but sends the output to the
terminal as well as to a file. ls tee dir.log will
display the names of the files in your directory on
your terminal and will put them in the file dir.log.
Creates a log file which is a record of your
terminal session. script myfile.log will create a file
named myfile.log and will copy all text that is
displayed on the monitor into myfile.log. If no
filename is specified, the default file is typescript.
Enables sending and receiving of mail.
mail user will send an e-mail to user. Type the text
of the letter following this command. Type C-d on
a new line to end the letter and send it to user. If
you have received mail, typing mail will allow you
to read them (see also cmm).
Shows a list of mail commands.
Displays a screen full of headers of the current
messages.
Displays a message on your terminal. t 2 will
display message number 2 on your terminal.
Displays the next message on your terminal.
Allows you to edit one of your messages. e 2
invokes the editor for message number 2.
Deletes a message. d 2 will delete message
number 2.
Undeletes a message. u 2 will undelete message
number 2.
Appends (saves) a message to a file. s 2 msg.txt
will put message 2 at the end of the file msg.txt.
Replies to a message. r 2 will send a reply to the
sender of message number 2.
Will send mail to another user. m user will
send mail to user.
Quits the mail program, expurges deleted
messages and moves (by default) current messages
to a file named mbox in your home directory.
Quits the mail program without changing the
system mailbox.
Appendix B
vi Editor Command Reference Guide
61
vi Editor Command Reference Guide


}
The variable n indicates a number as part of a command.
Where this variable is enclosed in parenthesis, it
represents an optional number argument. For example,
(n)^D indicates that the ^D command may or may not
be preceded by a number.
Unless otherwise stated, all escape mode cursor
movements can be the address of any escape mode
editing command that takes a following address.
[[
]]
“
EXITING vi
:w
Writes the editing buffer to disk. If you specify
a following filename, writes the buffer to a file with
that name.
:q
Exits vi without writing to disk.
:wq
Writes the file to disk and then quits.
:x
Writes the buffer to disk only if changes have
been made since the last write then quits.
ZZ
Same as :x.
Q
Puts you in ex command mode. Use the ex
command vi to get back into visual mode.
‘
‘x
`x
+
-
Moves to beginning of next paragraph (see
preceding command).
Moves to beginning of current or preceding
section where a section is marked with one of the
nroff paragraph macros. Type :set all to see what
these are.
Moves to beginning of next section (see preceding
command).
Moves to location where last major motion
command was given.
Repeats last search with f, F, t, or T, but reverses
direction.
Moves to exact location on line marked x (marked
with the m command).
Move to the start of the line maked with x (marked
with the m command).
Moves up one line.
Moves down one line.
SCREEN CONTROL COMMAND
^F
Pages forward one screenful. Cannot be used as a
cursor movement address.
^B
Pages back one screenful. Cannot be used as a
cursor movement address.
(n)^D
Scrolls down half a screen or n lines. Cannot be
used as a cursor movement address.
(n)^U
Scrolls up half a screen or n lines. Cannot be used
as a cursor movement address.
^R or ^L Redraws the screen when it has been scrambled by
a system message, a message from another user, or
some other interruption.
(n)zsize Redraws the screen with the current line or line n
at the top of the screen. If size is specified, the
screen is redrawn with that number of lines.
(n)zsize. Redraws the screen with the current line or line n
at the middle of the screen. If size is specified, the
screen is redrawn with that number of lines.
(n)zsize_ Redraws the screen with the current line or line n
at the bottom of the screen. If size is specified, the
screen is redrawn with that number of lines.
CURSOR MOVEMENTS
b
Moves back one word (bounded by punctuation
or whitespace).
B
M oves back one word (bounded by whitespace).
e
Moves to the end of current or next word.
E
Moves to the end word until whitespace character.
f
Moves to next occurrence on the current line of
the character you type next.
Fx
Moves to previous occurrence on the current line
of the character you type next.
(n)G
Moves to last line of file or line number n.
h
Move back one space.
j
Moves down one line.
k
Moves up one line.
l
Moves forward one space.
(n)L
Moves to bottom of screen or n lines from bottom.
M
Moves to beginning of middle line of screen.
tx
Moves to the space before the next occurrence of
character x on the current line.
Tx
Same as t but scans backwards on current line.
w
Moves to beginning of next word (bounded by
punctuation or whitespace).
W
Moves to beginning of next word (bounded by
whitespace).
S
Moves to last character of current line.
%
Moves to ), ], or } matching next occurrence of (, [
or {, respectively.
^
Moves to first nonwhitespace character on current
line.
(
Moves to beginning of current or previous
sentence.
)
Moves to beginning of next sentence.
&
Repeats last substitution (executed with last line
command s) on current line.
{
Moves to beginning of current or previous
paragraph where a paragraph is marked with one of
the nroff paragraph macros. Type :set all to see
what these are.
EDITING COMMANDS
a
Appends text after the cursor.
A
Appends text at end of current line.
cc
Changes one line to the next text typed.
cx
Changes from cursor to place delimited by cursor
movement x.
C
Changes current line from cursor to end.
dd
Deletes one line.
dx
Deletes from cursor to place delimited by cursor
movement x.
D
Deletes from cursor to end of current line.
i
Inserts text before the cursor.
I
Inserts text at beginning of current line.
J
Joins current line and next line.
mx
Marks current line (and current cursor position)
with letter x.
o
Opens new line below the current line.
O
Opens new line above the current line.
62
p
“np
“xp
cursor.
P
“nP
“xP
r
next
R
s
S
u
U
x
X
yy
Y
“xyy
&
~
(n)>
(n)<
with letter x.
Replaces last deleted, copied or changed text after
the cursor.
Places text in delete buffer n after the cursor.
Places text in named delete buffer x after the
LAST LINE EDITING COMMANDS
x,y(d)
Deletes lines with addresses x through y.
x,y (m)z Moves lines with addresses x through y to below
line with address z.
x,y (co)z Copies lines with addresses x through y to below
line with address z.
x,y s/pat1/pat2/(g)(c)
Replaces search pattern pat1
with replacement pattern pat2 on lines with
addresses x through y. If g is set, substitutes for
every occurrence of pat1 on specified lines. If c is
set, asks you to confirm each substitution.
g/pat1/s//pat2/(g)(c)
Same as above but makes
substitution on every line in the file containing
pat1.
Replaces last deleted, copied or changed text before
the cursor.
Places text in delete buffer n before the cursor.
Places text in named delete buffer x before the
cursor.
Replaces the character the cursor is on with the
character typed.
Replaces one character at a time with characters
typed next.
Substitute the next character typed for the character
the cursor is on.
Changes current line (identical to cc).
Undoes last editing command.
Undoes all editing changes to the current line.
Deletes character the cursor is on.
Deletes character before the cursor.
Copies current line.
Copies current line (identical to yy).
Copies current line into delete buffer x.
Repeats last substitution (last line command) on
current line (pattern must be matched).
Changes the case of the letter the cursor is on
(upper to lower or lower to upper). Cannot be
preceded by a number.
Shifts n lines right by the value of the ShiftWidth
option.
Shifts n lines left by the value of the ShiftWidth
option.
vi ENVIRONMENT OPTIONS
all
Displays a list of all the currently set option values.
autoindent (ai)
Used for writing structured programs
where indentation is important for determining
levels of embedded commands. When set, vi
indents each line you type an appropriate amount
dependent on the indentation of the previous line.
autoprint (ap)
Displays the current line after each
copy, move, or substitution (s) command.
ignorecase
When set, the case of letters in regular
expressions (in search patterns) is ignored except in
ranges within square brackets.
magic
When nomagic is set, all magic characters (used in
regular expressions) except ^ (beginning of line)
and $ (end of line) lose their magic properties. By
default, magic is set but even when nomagic is set,
you can turn on the magic of individual characters
by preceding them with \ (backslash).
mesg
By default, nomesg is set. When set, mesg allows
other users to write to your terminal with the write
command which can temporarily scramble your
screen.
number When set, the number of each line is displayed at
the left of the screen.
report
report=5 is set by default. This option determines
the threshold at which the number of lines deleted,
copied, moved or changed is reported.
showmatch
When this optionis set, each time a ) or }
is typed in insert mode, the cursor jumps quickly
back to show the matching ( or {.
showmode
Causes the message “INPUT MODE” to
be displayed in the lower right corner of the screen
when you are in insert mode.
wrapmargin
By default, wrapmargin=0 is set. When
a different numerical value is set, causes a
RETURN to be inserted that number of characters
from the right edge of the screen in insert mode.
SEARCHING
f
Finds next occurrence on the current line of the
character typed next.
F
Finds previous occurrence on the current line of the
character typed next.
tx
Moves to the space before the next occurrence of
character x on the current line.
Tx
Same as t but scans backwards on the current line.
,
(comma). Repeats last search with f, F, t or T but
reverses direction.
Searches for next occurrence of expr (any regular
/expr
expression in the file.
?expr Searches for previous occurrence of
expr (any
regular expression in the file.
n
Repeats last search with / or ?.
N
Repeats last search with / or ? but reverses
direction
of search.
MISCELLANEOUS ESCAPE MODE COMMANDS
“x
Names delete buffers. Puts next deleted, changed
or copied text in named buffer x.
^G
Displays at the bottom of the screen the current line
number and information about the length of the file.
mx
Marks current line (and current cursor position)
63
wrapscan
When set, vi treats a file as a continuous
loop for searches with / and ?. When nowrapscan
is set, a search with / stops scanning when it
reaches the end of the file and a search with ? stops
scanning when it reaches the beginning of the file.
str, a string abbreviation specified with :ab
command.
:map str1 str2
Maps str1, where str1 is any sequence of
characters, that will expand to str2 when typed in
escape mode.
:unmap str
Unmaps str, a string mapped with the
map command.
(address1, address2) w (file) Writes lines with addresses
address1 through address2 to a file called file.
(address) r file
Reads the file file into the current file
below the current line. If an address is specified,
reads the file in below the specified line.
MISCELLANEOUS LAST LINE COMMANDS
=
Displays the current line number.
:ab str1 str2
Designates str1 as an abbreviation that
will expand to str2 (any word or phrase) when
typed in insert mode.
:unab str Unabbreviates (removes the special significance of)
64