============================= = Lec-3-HW-3-LC3-PC ============================= You have seen the three states of the fetch phase of instruction execution. The three controller states accomplish the following: (F1) increment the PC and copy the content of the PC to the MAR (in parallel); (F2) copy the memory's output to the MDR, repeating until the memory signal R=1 indicates the memory unit finished the read operation; and (F3) copy the MDR content to the IR. In LC3 documentation those three states are given the labels state-18, state-33, and state-35, respectively. See docs/LC3-PPappendC and docs/LC3-ControlStates.txt. As we will see later, the clock signal, "sys_clk", triggers the registers to accept the data on their inputs. This is called a register write, and it overwrites the data that was in the register before the clock pulse arrived. For state-18 (F1), the PC's value is sent to the MAR and an incrementer, and from the incrementer to the PC's inputs. So, if the PC=1234 before, the MAR=1234 and the PC=1235 after the clock pulses. Your job in this assignment is to get the PC increment working. If you haven't already, copy the Electric .jelib library files from projects/LC3-trunk/lib to your branch's lib directory. Using Electric, open the "top" cell in the "system.jelib" library. (My notation in future will be "system.jelib:top".) Investigate the bus connections and verify whether or not the required connections exist between the PC's output and the incrementer and back to the PC's input. Repair as needed. That is one-third of the job. You will notice in docs/LC3-PPappendC that the incrementer (labeled "+1") sends its output to a MUX, and from the MUX the signal goes to the PC's input. There is a MUX select control signal. The LC3's controller, aka the micro-sequencer, has instance name "uSeq", and is an instance of uControl.jelib:uSeq. All control signals come from uSeq. This includes the MUX's select signal PCMUX[1:0]. In order for the signal from the "+1" unit to be sent to the PC's inputs, the PCMUX signal must be set correctly for state-18. Also, the PC will not accept the input, i.e., there won't be a register write, unless the PC's write-enable signal, LD_PC, is also set correctly for state-18. Aside from making the necessary bus and wire connections so that signals can get from source to destination, the needed control signals must be set. uSeq contains a memory in which all control signal values are stored. That memory is addressed by the current state of uSeq. When uSeq is in state-18, the memory word at address 18 is fetched, and the various bits of that word are connected to the control signal wires and busses at uSeq's outputs. The content of that memory is specified in uStore.jelib:uStore. Conveniently, each control signal has its own table there. So, rather than worry about an entire, 50-bit control word, you can focus on each control signal separately. All the signals already have verilog code to initialize them to 0. Your job is to fix these signals as needed. For instance, in uStore, you will find verilog code for LD_PC. Since in state-18 you want the PC to do a register write, you must have LD_PC=1 for that state. The syntax for that is, "LD_PC[18]=1'b1;". Note that all the various control signals are concatenated into a single bus, which is the uSeq's memory word output. The PCMUX signal also needs to be set similarly. That signal depends on which of the MUX's inputs you connected the "+1" output to. The MUX's inputs are labeled "00", "01", "10", and "11". If you connected to the "01" input, then for state 18 you will want PCMUX[18]=2'b01, for example. Notice that for those states in which the PC is not being written, it doesn't matter which input PCMUX selects since LD_PC=0 in that case (unless you mistakenly set it to 1). You will find docs/LC3-uArch-ConstrolStates.txt is a handy tool for you to use. It has, in text, a representation of the complete controller state diagram from PP's appendix C. Each state shows register-transfer language (RTL) for what needs to be done in that state. You will find it useful to fill in for each state whatever non-zero control signals should be set. Then use that to guide you as you edit uStore. TESTING: Create a new cell in test.jelib. Place an instance of system.jelib:top. Name the instance "top". Add a verilog code box. Since uSeq has a system clock that runs and sends pulses throughout the LC3, you do not need to stimulate any signals. What you do need to do is output signals so you can see what is happening. As I recall, the clock pulses every 20 simulation time ticks. Each state lasts for one clock cycle, and changes occur at the next clock pulse. Also, registers have a delay in propagating their input to their output when they are written. This delay is something like two ticks, if I recall. You will want to see what happens when. First, write an "initial" statement to $display() a hello message, wait 100 ticks, and $finish. Next, drop in another verilog code box. Write an "always @(top.sys_clk)" statement and display the simulation time using $time. This will tell you when the clock changed its output. Also $display() the sys_clk's value, $display( " (t=%0d) sys_clock = %b ", $time, top.sys_clk ); After that, put in a delay to allow the register outputs to change and any signals to propagate. Something like #5 will probably do. Then add code to $display whatever signals you need to see to determine whether the PC gets properly incremented. You will probably have to name a wire or bus so you can refer to it in your $display code. E.g., name a bus connected to the PC's output as "PC_out". Note that the "clock pulse" is considered to occur when sys_clk changes from 0 to 1. Remember to check Electic's message window when you do Tools.Simulation(Verilog).WriteVerilogDeck. It will have warning messages telling you if it found problems with your design. You can ignore the warning about sys_clk that says it is both an input and an output. You can also ignore any warnings about files not being opened for reading. WARININGS 1. Name your system.jelib:top instance: The instance icon shows the module name "top", but this is not the instance's name. Select the instance icon, and do, Edit.Object.ObjectProperties to change its instance name. 2. Name your signals by their bus size: The output from the PC is 16 bits. Suppose you gave the bus attached to it the name "PC_out". That will disconnect bus wires in the resulting verilog code. Use "PC_out[15:0]". WHAT TO TURN IN: Turn in a cover sheet. In your comments section, explain how you went about altering your copy of the LC3 design. That is, detail what connections were made and what control signals were set to what values. Test your implementation, and describe the results of your tests and any problems you detected. Of course, check in your modifications to your branch. Do not wait to check in until you have everything working: Make some changes, check in, test, make more changes, check in, test ... Also check in the output from your tests. Recall that you can send a process's stdout output to a file instead of the screen: %> vvp a.out > test-1.out for example, sends whatever output "vvp a.out" produces to the file "test-1.out".