ProblemDescription
ProblemDescription
ProblemDescription
com/reds-
heig/logisim-evolution/releases/tag/v2.15.0).
The starter files are in the subfolder named base and the instructions for testing are in the file named
test instructions.
Constraints
You may use anything from the following for this problem:
You may not use ROMs or RAM; doing so will result in a 0. Make your storage out of register
modules. ROMs are explicitly disallowed. Adders and subtractors are also explicitly disallowed.
Make them via gates.
Background
Your final task (at least, in terms of the labs) will be to build a single cycle CPU. This is
considered a rite of passage for computer architecture courses. This CPU will be 8 bits wide, and
can do various register transfers and ALU operations using point-to-point connections.
In typical fashion for this course, the first couple of problems in this lab have you implement
pieces of the CPU in isolation and test them for correct operation. We start small and build our
way up. This is also set up this way so that you can get some partial credit if you can't complete
the entire thing. However, a good portion of credit for the lab will come from the final problem
where you combine your pieces and create a working CPU. It's much more important to
understand how these pieces fit together and build off of each other, hence the point setup.
CPU Diagram
You should follow the diagram below when building your CPU. Some of the control wires are
not on the diagram. You will need to figure out how to implement those yourself.
In the following problems, you will implement the following portions. See the individual
problems for more information on each portion.
1. ALU
2. PC and RAM
3. Register File
4. A Select Unit, B Select Unit, Control Unit, and connecting everything together
The design for this machine is different from any that have been produced in industry. However,
it does draw heavily from some previous designs. Some of the naming conventions for signals in
the diagram above have been borrowed from the open-source RISC-V instruction set
architecture. The meaning of some of the names is below:
However, this is not a RISC-V machine. In case you are interested in learning more about RISC-V,
or building your own CPUs in something other than Logisim Evolution, I'd highly recommend
taking ECS 154B. You build multiple RISC-V CPUs in that class using a hardware design language
(HDL) called Chisel.
Instruction Format
The following table describes how a 21-bit instruction for this CPU will be formatted:
Nam
Bits Function in CPU Description
e
16 - Register File
rd Destination register specification.
14 Register Select
13 - A Select Unit
rs1 Primary source register specification.
11 Control
Operation Description
The following table describes what the opcode from the table above corresponds to in terms of
operation. All operations, except for NOP, HLT, and HCF, place their results in the destination
register rd.
op
Operatio
[20- Description
n
17]
SLL stands for Shift Left Logical. Example: 1011 -> 0110.
Create an 8-bit ALU. This portion of the CPU handles the calculations based on stored and
current input values.
Operations
Based on the opcode, the ALU will perform a certain operation. The result of the operation is
output as rddata. For details on which operation is which op value, check the Operation
Description section above.
Note that NOP, HLT, and HCF don't actually use the ALU. Those opcodes won't be provided in
this problem. When combining everything together, you will need to figure out how to handle
those three instructions.
If you are importing your CLA from a previous part, don't use the Load Library
feature! The autograder expects only the named files. Your CLA and any other subcircuits needs
to be in the same file as your main circuit file, not a separate one. You can use
the Merge... feature instead to import your CLA or other subcircuit.
For the adder and subtractor, you must use carry look-ahead for each group of 4 bits. Note that
you have already built a 4-bit CLA unit in Lab 2, assuming we didn't mark you for rippling the
carry.
Below is a clarification on what carry look-ahead means. There was a lot of confusion on this in
the last lab, which is why I changed it to not deduct any points if you did build a ripple-carry
adder. A carry look-ahead unit calculates all carries at the same time using all the propagator
and generator bits, without reusing any carry bits. A carry bit you calculate should not feed into
any other logic, nor should you duplicate the logic for a carry bit to use in another piece of logic.
Since you are using carry look-ahead for each group of 4 bits, C4 should be used as the base for
C5, C6, and C7. This means that:
You should have a maximum of 8 OR gates across both CLAs. You should be able to figure out
how to reuse your previous CLA unit here, if it was correct. You may disregard the final carry out.
This time, you will be deducted points if you build a ripple-carry adder. If anything above is
confusing, look at the lecture notes on adders, or ask on Campuswire.
Create the program counter (PC) and the random access memory (RAM) that stores the
instructions and outputs the current instruction. This portion of the CPU gives the commands to
the remainder of the CPU to calculate and store values.
Program Counter
The PC will be an 8-bit up-counter that starts at 0 and wraps around upon saturation. You may
use the built-in counter module to do so. I have to allow registers for the next part, and you can
make a counter pretty easily out of a register and an adder or ALU.
The output of the PC, pc, will feed the RAM the memory location of the instruction it should
output. In addition, you will need to attach the resetall signal to the reset pins of the flip flops in
your PC. When resetall is asserted, the PC should be reset to 0. This is used to reset the CPU
back to the start.
The output of the PC, pc, will be fed to a 256 entry x 21 data RAM module with separate load
and store ports. We will only use the RAM as a source of instructions, so we will not use the
store port. The address bits will be sourced from the output of your PC. The output of the RAM
will be the relevant pieces of the instruction that you should be executing on this cycle.
Make sure to change the databus implementation over to separate databuses for reading and
writing. You will need to hook up sysclock to the C3 pin of the RAM. In addition, make sure to
hook up a ground module to the M1 pin of the RAM, and a power module to the M2 pin of the
RAM. Doing these will ensure that the RAM outputs the instruction value and does not attempt
to overwrite any data.
Loading Programs
If you are manually testing this subcircuit, you will want to set the initial contents of your RAM
to the tester file ram/cpu.txt. If you click on the RAM, on the left sidebar there is an option
for Initial contents that you'll want to use.
When you are testing this via the tester, you'll need to make a slight change to the command
line argument you use. You should add -load ram/4.txt to the end of the command. This tells
Logisim Evolution to load the RAM in your subcircuit with the expected program. Thus, a full
command for the tester for this part will look like this:
java -jar logisim-evolution.jar tester/2tester.circ -tty table -load
ram/cpu.txt > output.txt
diff output.txt tsv/2.tsv
There should only be one RAM in this circuit or any subcircuits used in this file. Make sure the
address and data sizes are correct. We will attempt to load the RAM with the tester program via
the -load command line argument. This command will attempt to load every RAM with the file
we specify. Having more than one will lead to undesired results. Using a ROM will prevent us
from loading programs and you will get a 0.
Create an eight-bit eight-register register file. This portion of the CPU provides the storage for
the rest of the CPU.
Although a CPU would normally store output in memory (RAM), we will not be dealing with
memory in this lab. Instead, we will treat the values of the registers as the "output" of this CPU,
hence all the output pins.
On the rising edge of sysclock, if the wen signal is asserted, the register corresponding to the
appropriate rd value will be written with rddata. The registers' current values will be output
as x0 through x7. Hint: much like the Hamming(7,4) circuit, a decoder will be very useful here.
Note that in this problem, wen will be provided for you. You should hook this up to the
appropriate pin on the register module. When combining everything together, you will need to
determine when wen should be 0 or 1.
Additionally, you will need to attach the resetall signal to the reset pin of your registers. When
this signal is asserted, all registers should be reset to 0. This is used to reset the CPU back to the
start.
You should (and effectively must) use registers to implement this problem. Flip flops don't have
a write enable pin, which causes an interesting side effect when playing with the clock on
attempting to disable a write.
You may not use RAM to implement your register file; doing so will result in a 0 for this problem.
Using a RAM will cause your CPU to break when we use the -load command line argument for
the next problem.
4. Single Cycle CPU [40]
Finally, put all the pieces together from the previous parts and build your single cycle CPU
according to the diagram. A good portion of credit for the lab is on this problem.
This part doesn't take many extra components to implement, not including the subcircuits for
the previous parts. You shouldn't be adding a ton of extra logic here, but you will need to spend
some time and think about what you're implementing. When importing the subcircuits from the
previous parts, you can use the Merge... option under File in the menu bar. This way, you don't
need to copy and paste.
Your only input pins here are sysclock and resetall. sysclock is used to make sure the tester circuit
and your CPU stay in lockstep. resetall won't be used for this part but may be helpful for your
manual testing. Make sure to hook these inputs up to both the PC, the register file, and any flip
flops you add in this circuit specifically.
Here's some more detail on the other parts of the CPU you haven't implemented yet:
A Select
This multiplexer selects between the different registers for the A input into the ALU. rs1 specifies
which register becomes A.
B Select
This unit selects between the different registers or the immediate data input imm for the B input
into the ALU. rs2 will specify which register becomes B, but this doesn't apply for every
instruction. When we say "immediate value," we mean the last 8 bits contained with the
instruction itself. For the MOVI, ADDI, and SUBI instructions, the B data source to the ALU should
be the 8 bits from the instruction, instead of the value from the register specified by rs2. This is
why imm feeds into the B select logic.
You will need to figure out this block of logic by yourself. It will look similar to the A Select unit
above, but not exactly the same.
Program Counter Special Cases
There are two special cases you need to deal with for the PC that you did not need to deal with
before. Control wires from your control unit will be a good way to handle these cases. It is up to
you to figure out how to implement the functionality for both.
It is possible to implement both of these special cases without modifying your subcircuits for
any of the pieces you've made already. Feel free to modify your subcircuits for those parts if you
think you need to. That said, make sure to only modify the subcircuits inside this problem
instead of your previous ones. If you make changes to the previous ones, then they may fail the
autograder.
Control Unit
The control unit contains the logic to set the ALU to perform the correct operation. You can
pass op along as is to the ALU.
The control unit also generates control wires for the rest of the CPU to use. The exact wires are
up to you. Here are some recommendations:
Loading Programs
If you are manually testing this subcircuit, you will want to set the initial contents of your RAM
to the tester file ram/cpu.txt. If you click on the RAM, on the left sidebar there is an option
for Initial contents that you'll want to use.
When you are testing this via the tester, you'll need to make a slight change to the command
line argument you use. You should add -load ram/cpu.txt to the end of the command. This
tells Logisim Evolution to load the RAM in your subcircuit with the expected program. Thus, a
full command for the tester for this part will look like this:
java -jar logisim-evolution.jar tester/4tester.circ -tty table -load
ram/cpu.txt > output.txt
diff output.txt tsv/4.tsv
There should only be one RAM in this circuit or any subcircuits used in this file. Make sure the
address and data sizes are correct. We will attempt to load the RAM with the tester program via
the -load command line argument. This command will attempt to load every RAM with the file
we specify. Having more than one will lead to undesired results. Using a ROM will prevent us
from loading programs and you will get a 0.
Assembler
There is a Python 3 script inside the assembler/ subdirectory. You can use this to build your own
programs for further testing or your own experimentation.
Use the -h flag to understand how the assembler expects its command line arguments. The
input CSV file should look similar to ram/cpu.csv.
Other Considerations
If you add any other flip flops to your circuit here, make sure to hook them up to sysclock so
they stay in sync with the grader circuit. Also, make sure to hook up the resetall pin to them as
well so that they reset correctly.
5. Transaction ledger [15]
Background
Hsakaa, Treepnura, Tihcra, and Nitsuj (names changed to protect the innocent) are regulars at
the Sankiro Brewery in Davis. One night, during a drunken haze, they had a brilliant idea, or so
they thought. Why should Sankiro keep paying a percentage fee (somewhere around 2.5%) and
flat fee (somewhere around $0.15) per transaction to credit card companies like Asiv or
Dracretsam (names changed to avoid potential legal liability) to handle credit card transactions?
If they just built a transaction ledger, and everybody was honest about it, then Sankiro could
make their beers cheaper, and thus the group could order more beer for the same amount of
money!
1. They came up with this idea after reaching, then obliterating, the Ballmer peak
2. They thought people would be honest on the ledger
3. They thought Sankiro would make their beers cheaper if they didn't have to pay
transaction fees anymore
4. The group thought they would actually be able to handle the increased amount of beer
they thought they'd be getting
You'll notice that the thing that's not on the list above is "it's impossible to create the
transaction ledger." Nitsuj is lazy and is outsourcing it to his SCE A451 students as extra credit.
However, Nitsuj believes that extra credit should truly be "extra." While he's providing a
framework here, it's up to the students to figure out some parts.
Details
There will only be 8 customers you need to handle; each one has a unique customerid. You may
assume that each customer's balance is 0 at the start. The maximum amount is $255; we don't
bother with cents here. Each clock cycle, a new transaction request will come in with
a customerid, transactiontype, and transactionamount. You will need to handle the transaction
and output the appropriate transactionresult and amountremaining in that customer's balance.
You can treat all balances and transaction amounts as unsigned numbers. Hint: one of the
output pins of the arithmetic modules you will use provides a simple way of handling overflows
and underflows.
The tester file for this part contains two programs. The first one is a randomized stress tester
using a pseudo-random number generator. This is what your extra credit problem will be tested
upon for correctness.
If you would like to change between the two for your testing purposes, change the constant
for programchoice inside the tester file to 0 or 1.