0% found this document useful (0 votes)
35 views

Verilog Lab9

VHDL simple microprocessor prototype.

Uploaded by

sikandara819
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
35 views

Verilog Lab9

VHDL simple microprocessor prototype.

Uploaded by

sikandara819
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

A Simple Processor

Figure 1 shows a digital system that contains a number of 16-bit registers, a multiplexer, an adder/subtracter,
and a control unit (finite state machine). Information is input to this system via the 16-bit DIN input, which is
loaded into the IR register. Data can be transferred through the 16-bit wide multiplexer from one register in the
system to another, such as from register IR into one of the general purpose registers r0, . . . , r7. The multiplexer’s
output is called Buswires in the figure because the term bus is often used for wiring that allows data to be trans-
ferred from one location in a system to another. The FSM controls the Select lines of the multiplexer, which allows
any of its inputs to be transferred to any register that is connected to the bus wires.

The system can perform different operations in each clock cycle, as governed by the FSM. It determines when
particular data is placed onto the bus wires and controls which of the registers is to be loaded with this data. For
example, if the FSM selects r0 as the output of the bus multiplexer and also asserts Ain, then the contents of
register r0 will be loaded on the next active clock edge into register A.

Addition or subtraction of signed numbers is performed by using the multiplexer to first place one 16-bit number
onto the bus wires, and then loading this number into register A. Once this is done, a second 16-bit number is
placed onto the bus, the adder/subtracter performs the required operation, and the result is loaded into register G.
The data in G can then be transferred via the multiplexer to one of the other registers, as required.
16

16 16 16 16
Ain
r0 in r7 in
r0 r7 A

Clock
AddSub
Adder/Subtracter

16
Gin
Multiplexer
G

16

Select Buswires

4
IR in

16
DIN IR

Run Control unit FSM

Resetn
Done

Figure 1: A digital system.

1
A system like the one in Figure 1 is often called a processor. It executes operations specified in the form of
instructions. Table 1 lists the instructions that this processor supports. The left column shows the name of an
instruction and its operands. The meaning of the syntax rX←Op2 is that the second operand, Op2, is loaded into
register rX. The operand Op2 can be either a register, rY, or immediate data, #D.

Instruction Function performed


mv rX, Op2 rX ← Op2
mvt rX, #D rX15−8 ← D7−0
add rX, Op2 rX ← rX + Op2
sub rX, Op2 rX ← rX − Op2

Table 1: Instructions performed in the processor.

Instructions are loaded from the external input DIN, and stored into the IR register, using the connection indicated
in Figure 1. Each instruction is encoded using a 16-bit format. If Op2 specifies a register, then the instruction
encoding is III0XXX000000YYY, where III specifies the instruction, XXX gives the rX register, and YYY
gives the rY register. If Op2 specifies immediate data #D, then the encoding is III1XXXDDDDDDDDD, where
the field DDDDDDDDD represents a nine-bit signed (2’s complement) value. Although only two bits are needed to
encode our four instructions, we are using three bits because other instructions will be added to the processor later.
Assume that III = 000 for the mv instruction, 001 for mvt, 010 for add, and 011 for sub.

The mv instruction (move) copies the contents of one register into another, using the syntax mv rX,rY. It can also
be used to initialize a register with immediate data, as in mv rX,#D. Since the data D is represented inside the en-
coded instruction using only nine bits, the processor has to sign-extend the data, as in D8D8D8D8D8D8D8D8−0,
before loading it into register rX. The mvt instruction (move top) is used to initialize the most-significant byte of
a register. The instruction mvt rX,#D loads the 16-bit value D7−000000000 into rX. As an example, to load
register r0 with the value 0xFF00, you would use the instruction mvt r0,#0xFF. The instruction add rX,rY
produces the sum rX + rY and loads the result into rX. The instruction add rX,#D produces the sum rX + D,
where D is sign-extended to 16 bits, and saves the result in rX. The sub instruction generates either rX − rY, or rX
— #D and loads the result into rX.

Some instructions, such as an add or sub, take a few clock cycles to complete, because multiple transfers have to
be performed across the bus. The finite state machine in the processor “steps through” such instructions, asserting
the control signals needed in successive clock cycles until the instruction has completed. The processor starts
executing the instruction on the DIN input when the Run signal is asserted and the processor asserts the Done
output when the instruction is finished. Table 2 indicates the control signals from Figure 1 that have to be asserted
in each time step to implement the instructions in Table 1. The only control signal asserted in time step T0, for
all instructions, is IRin. The meaning of Select rY or IR in the table is that the multiplexer selects and puts onto
the bus (BusWires) either the contents of register rY or the immediate data in IR, depending on the value of Op2.
For the mv instruction, when IR is selected the multiplexer outputs DDDDDDDDD sign-extended to 16 bits, and for
mvt the multiplexer outputs DDDDDDDD00000000. Only signals from Figure 1 that have to be asserted in each
time step are listed in Table 1; all other signals are not asserted. The meaning of AddSub in step T2 of the sub
instruction is that this signal is set to 1, and this setting causes the adder/subtracter unit to perform subtraction
using 2’s-complement arithmetic.

The processor in Figure 1 can perform various tasks by using a sequence of instructions. For example, the sequence
below loads the number 28 into register r0 and then calculates, in register r1, the 2’s complement value −28.

mv r0, #28 // original number = 28


mvt r1, #0xFF
add r1, #0xFF // r1 = 0xFFFF
sub r1, r0 // r1 = 1’s- complement of r0
add r1, #1 // r1 = 2’s- complement of r0 = -28

2
This sequence of instructions produces the same result as the single instruction mv r1,#-28.

T0 T1 T2 T3
mv IRin Select rY or IR,
rXin, Done
mvt IRin Select IR,
rXin, Done
add IRin Select rX, Select rY or IR, Select G, rXin,
Ain Gin Done
sub IRin Select rX, Select rY or IR, Select G, rXin,
Ain AddSub, Gin Done

Table 2: Control signals asserted in each instruction/time step.

Part I
Implement the processor shown in Figure 1 using Verilog code, as follows:
1. Make a new folder for this part of the exercise. Part of the Verilog code for the processor is shown in parts
a to c of Figure 2, and a more complete version of the code is provided with this exercise, in a file named
proc.v. You can modify this code to suit your own coding style if desired—the provided code is just a
suggested solution. Fill in the missing parts of the Verilog code to complete the design of the processor.

module proc(DIN, Resetn, Clock, Run, Done);


input [15:0] DIN;
input Resetn, Clock, Run;
output Done;
. . . declare variables

assign III = IR[15:13];


assign IMM = IR[12];
assign rX = IR[11:9];
assign rY = IR[2:0];
dec3to8 decX (rX_in, rX, R_in); // produce r0 - r7 register enables

parameter T0 = 3’b000, T1 = 3’b001, T2 = 3’b010, T3 = 3’b011;


// Control FSM state table
always @(Tstep_Q, Run, Done)
case (Tstep_Q)
T0: // data is loaded into IR in this time step
if (~Run) Tstep_D = T0;
else Tstep_D = T1;
T1: . . .
...
endcase

Figure 2: Skeleton Verilog code for the processor. (Part a)

3
parameter mv = 3’b000, mvt = 3’b001, add = 3’b010, sub = 3’b011;
// selectors for the BusWires multiplexer
parameter _R0 = 4’b0000, _R1 = 4’b0001, _R2 = 4’b0010,
_R3 = 4’0011, . . ., _R7 = 4’b0111, _G = 4’b1000,
_IR8_IR8_0 /* signed- extended immediate data */ = 4’b1001,
_IR7_0_0 /* immediate data << 8 */ = 4’b1010;

// control FSM outputs


always @(*) begin
rX_in = 1’b0; Done = 1’b0; . . . // default values for variables
case (Tstep_Q)
T0: // store DIN into IR
IR_in = 1’b1;
T1: // define signals in time step T1
case (III)
mv: begin
if (!Imm) Select = rY; // mv rX, rY
else Select = _IR8_IR8_0; // mv rX, #D
rX_in = 1’b1; // enable rX
Done = 1’b1;
end
mvt: // mvt rX, #D
...
endcase
T2: // define signals in time step T2
case (III)
...
endcase
T3: // define signals in time step T3
case (III)
...
endcase
default: ;
endcase
end

// Control FSM flip- flops


always @(posedge Clock, negedge Resetn)
if (!Resetn)
...

regn reg_0 (BusWires, Resetn, R_in[0], Clock, r0);


regn reg_1 (BusWires, Resetn, R_in[1], Clock, r1);
...
regn reg_7 (BusWires, Resetn, R_in[7], Clock, r7);

. . . instantiate other registers and the adder/subtracter unit

Figure 2: Skeleton Verilog code for the processor. (Part b)

4
// define the internal processor bus
always @(*)
case (Select)
_R0: BusWires = r0;
_R1: BusWires = r1;
...
_R7: BusWires = r7;
_G: BusWires = G;
_IR8_IR8_0: BusWires = {{7{IR[8]}}, IR[8:0]};
_IR7_0_0: BusWires = {IR[7:0], 8’b00000000};
default: BusWires = 16’bxxxxxxxxxxxxxxxx;
endcase
endmodule

module dec3to8(E, W, Y);


input E; // enable
input [2:0] W;
output [0:7] Y;
reg [0:7] Y;

always @(*)
if (E == 0)
Y = 8’b00000000;
else
case (W)
3’b000: Y = 8’b10000000;
3’b001: Y = 8’b01000000;
3’b010: Y = 8’b00100000;
3’b011: Y = 8’b00010000;
3’b100: Y = 8’b00001000;
3’b101: Y = 8’b00000100;
3’b110: Y = 8’b00000010;
3’b111: Y = 8’b00000001;
endcase
endmodule

Figure 2: Skeleton Verilog code for the processor. (Part c)

2. Set up the required subfolder and files so that your Verilog code can be compiled and simulated using the
Questa or ModelSim Simulator to verify that your processor works properly. An example simulation result
for a correctly-designed circuit is given in Figure 3. It shows the value 0x101C being loaded into IR from
DIN at time 30 ns. This pattern represents the instruction mv r0,#28, where the immediate value D = 28
(0x1C) is loaded into r0 on the clock edge at 50 ns. The simulation results then show the instruction
mvt r1,#0xFF at 70 ns, add r0,#0xFF starting at 110 ns, and sub r1,r0 starting at 190 ns.
You should perform a thorough simulation of your processor. A sample Verilog testbench file, testbench.v,
execution script, testbench.tcl, and waveform file, wave.do are provided along with this exercise.

5
Figure 3: Simulation results for the processor.
Part II
In this part we will design the circuit illustrated in Figure 4, in which a memory module and counter are connected
to the processor. The counter is used to read the contents of successive locations in the memory, and this data is
provided to the processor as a stream of instructions. To simplify the design and testing of this circuit we have
used separate clock signals, PClock and MClock, for the processor and memory.

You are to implement the circuit in Figure 4 in a suitable FPGA (for example, the DE1-SoC, DE10-Standard,
or DE10-Lite) board. As part of the process for designing and debugging the circuit, you must use the Questa
or ModelSim simulator to test your Verilog code’s functionality. Also, you can use the DESim tool as a way of
observing how your circuit will behave on an FPGA board, even if you do not have access to a physical board (for
example, at home). You are encouraged to make use of the DESim tool to help in the design and debug of your
Verilog code. This tool is available from FPGAcademy.org. To make it easy to use the DESim tool, the design
files for this part of the exercise include all required DESim setup files. Perform the following steps:
Processor
Memory
Counter

n 16
addr data DIN
Done Done
Resetn

Run

MClock
PClock
Resetn
Run

Figure 4: Connecting the processor to a memory module and counter.

1. A sample top-level Verilog file that instantiates the processor, memory module, and counter is shown in
Figure 5. This code is provided, along with this exercise, in a file named part2.v. It is the top-level Verilog
file for this part of the exercise. The code instantiates a memory module called inst_mem. A diagram of

6
this memory module is depicted in Figure 6. Since this module has only a read port, and no write port, it
is called a synchronous read-only memory (synchronous ROM). The memory module includes a register for
synchronously loading addresses. This register is required due to the design of the memory resources in the
Intel FPGA chip.
The synchronous ROM is defined in a Verilog source-code file named inst_mem.v, which is provided along
with this exercise. You can use the provided file, or you can create one yourself (if you want to see how this
is done) by using the Quartus Prime software. The instructions for creating the inst_mem.v file using the
Quartus software are given below. If you do not wish to perform these steps, and just want to make use of
the provided file, then skip to item 3, below.

module part2 (KEY, SW, LEDR);


input [1:0] KEY;
input [9:0] SW;
output [9:0] LEDR;

wire Done, Resetn, PClock, MClock, Run;


wire [15:0] DIN;
wire [4:0] pc;
assign Resetn = SW[0];
assign MClock = KEY[0];
assign PClock = KEY[1];
assign Run = SW[9];
proc U1 (DIN, Resetn, PClock, Run, Done);
assign LEDR[9] = Done;
inst_mem U2 (pc, MClock, DIN);
count5 U3 (Resetn, MClock, pc);
endmodule

module count5 (Resetn, Clock, Q);


input Resetn, Clock;
output reg [4:0] Q;

always @ (posedge Clock, negedge Resetn)


if (Resetn == 0)
Q <= 5’b00000;
else
Q <= Q + 1’b1;
endmodule

Figure 5: Verilog code for the top-level module.

2. A Quartus project file is provided along with this part of the exercise. Use the Quartus software to open this
project, which is called part2.qpf. The top-level file in this Quartus project is part2.v. Use the Quartus IP
Catalog tool to create the memory module, by clicking on Tools > IP Catalog in the Quartus software. In
the IP Catalog window choose the ROM: 1-PORT module, which is found under the Basic Functions >
On Chip Memory category. Select Verilog HDL as the type of output file to create, and give the file the
name inst_mem.v.
Follow through the provided dialogue to create a memory that has one 16-bit wide read data port and is
32 words deep. Figures 7 and 8 show the relevant pages and how to properly configure the memory.
In Figure 8, under Which ports should be registered?, ensure that the ‘q’ output port
is not selected. To place processor instructions into the memory, you need to specify initial values that
should be stored in the memory when your circuit is programmed into the FPGA chip. This can be done

7
5 5
Address
16
Clock 32 x 16 ROM DataOut

Figure 6: The 32 x 16 ROM with address register.

by initializing the memory using the contents of a memory initialization file (MIF). The appropriate screen
is illustrated in Figure 9. We have specified a file named inst_mem.mif, which then has to be created in
the folder that contains the Quartus project. Clicking Next two more times will advance to the Summary
screen, which lists the names of files that will be created for the memory IP. You should select only the
Verilog file inst_mem.v. Make sure that none of the other types of files are selected, and then click Finish.

Figure 7: Specifying memory size.

3. As described above, you need to provide a memory initialization file (MIF) called inst_mem.mif to specify
the contents of the ROM. An example of a memory initialization file is given in Figure 10. Note that com-
ments (% . . . %) are included in this file as a way of documenting the meaning of the provided instructions.
Set the contents of your MIF file such that it provides enough processor instructions to test your circuit.
4. The Verilog code in Figure 5 includes the appropriate port names for implementation of the design on
an FPGA board, like the DE1-SoC. The switch SW9 drives the processor’s Run input, SW0 is connected
to Resetn, KEY0 to MClock, and KEY1 to PClock. The Run signal is displayed on LEDR9 and Done is
connected to LEDR0.

8
Figure 8: Specifying which memory ports are registered.

Figure 9: Specifying a memory initialization file (MIF).

9
5. Use the Questa or ModelSim Simulator to test your Verilog code. Ensure that instructions are read properly
out of the ROM and executed by the processor. An example of simulation results with the MIF file from
Figure 10 is shown in Figure 11. The corresponding Simulator setup files are provided along with this
exercise.

6. Once your simulations show a properly-working circuit, you should implement your design on a DE1-SoC
(or similar) board. Use the Quartus project files that are provided along with this exercise to compile your
Verilog code with the Quartus Prime software, and then download the resulting circuit to the board.
Demonstrate the functionality of your circuit by toggling the switches on the board and observing the LEDs.
Since the circuit’s clock inputs are controlled by pushbutton switches, it is possible to step through the
execution of instructions and observe the behavior of the circuit.

DEPTH = 32;
WIDTH = 16;
ADDRESS_RADIX = HEX;
DATA_RADIX = BIN;
CONTENT
BEGIN
00 : 0001000000011100; % mv r0, #28 %
01 : 0011001011111111; % mvt r1, #0xFF %
02 : 0101001011111111; % add r1, #0xFF %
03 : 0110001000000000; % sub r1, r0 %
04 : 0101001000000001; % add r1, #1 %
05 : 0000000000000000;
. . . (some lines not shown)
1F : 0000000000000000;
END;

Figure 10: An example memory initialization file (MIF).

Figure 11: An example simulation output using the MIF in Figure 10.

Enhanced Processor
You can enhance your processor so that the counter in Figure 4 is no longer needed, and so that the processor
has the ability to perform read and write operations using memory or other devices. These enhancements involve
adding new instructions to the processor, as well as other capabilities—they are discussed in the next lab exercise.

10

You might also like