Download as pdf or txt
Download as pdf or txt
You are on page 1of 25

Verilog HDL

ECE 4680 Computer Architecture


Verilog Presentation 2

Outline
Half Adder and Testbench 4-to-1 Multiplexor 2-to-4 Decoder ALU Register File CPU

A Verilog module that defines a half-adder


1-bit adder: This adder is called a full adder; it is also called a (3,2) adder because it has 3 inputs and 2 outputs. An adder with only the a and b inputs is called a (2,2) adder or half adder.

1-bit Half Adder


module half_adder (A, B, Sum,Carry); input A,B; output Sum, Carry; assign Sum = A ^ B; assign Carry = A & B; endmodule //two 1-bit inputs //two 1-bit outputs //sum is A xor B //Carry is A and B

Test bench module for half adder module


module half_adder_test(); reg ia, ib; half_adder h1(ia,ib,S0,C0); Initial begin #0 ia=0; ib=0; #1 ia=0; ib=1; #1 ia=1; ib=0; #1 ia=1; ib=1; $finish end endmodule

4-to-1 Multiplexor
Sel In1 In2 In3 In4

MUX

Out

4-to-1 Multiplexor with four 32-bit inputs


module Mult4to1 (In1,In2,In3,In4,Sel,Out); input [31:0] In1, In2, In3, In4; // four 32-bit inputs input [1:0] Sel; // selector signal output reg [31:0] Out; // 32-bit output always @(In1, In2, In3, In4, Sel) case (Sel) // a 4->1 multiplexor 0: Out <= In1; 1: Out <= In2; 2: Out <= In3; default: Out <= In4; endcase endmodule

Decoder
en

Y3

Decoder
B

Y2 Y1 Y0

Decoder
module decoder 2 to 4 (Y3, Y2, Y1, Y0, A, B, en); output Y3, Y2, Y1, Y0; input A, B; input en; reg Y3, Y2, Y1, Y0;
always @(A or B or en) begin if (en == 1) case ( {A,B} ) 2'b00: {Y3,Y2,Y1,Y0} = 4'b1110; 2'b01: {Y3,Y2,Y1,Y0} = 4'b1101; 2'b10: {Y3,Y2,Y1,Y0} = 4'b1011; 2'b11: {Y3,Y2,Y1,Y0} = 4'b0111; default: {Y3,Y2,Y1,Y0} = 4'bxxxx; endcase

if (en == 0) {Y3,Y2,Y1,Y0} = 4'b1111; end endmodule

MIPS ALU in Verilog


The ALU has 7 ports. These ports are the two input ports a and b, the output result port, ALU Operation control, zero detect output, overflow detect output, and the carryout output.

A Verilog behavioral definition of a MIPS ALU


module MIPSALU (ALUctl, A, B, ALUOut, Zero); input [3:0] ALUctl; input [31:0] A,B; output reg [31:0] ALUOut; output Zero; assign Zero = (ALUOut==0); //Zero is true if ALUOut is 0 always @(ALUctl, A, B) begin //reevaluate if these change case (ALUctl) 0: ALUOut <= A & B; 1: ALUOut <= A | B; 2: ALUOut <= A + B; 6: ALUOut <= A - B; 7: ALUOut <= A < B ? 1 : 0; 12: ALUOut <= ~(A | B); //result is nor default: ALUOut <= 0; endcase end endmodule

The MIPS ALU control


a piece of combinational control logic. module ALUControl (ALUOp, FuncCode, ALUCtl); input [1:0] ALUOp; input [5:0] FuncCode; output [3:0] reg ALUCtl; always case (FuncCode) 32: ALUCtl <=2; // add 34: ALUCtl <=6; //subtract 36: ALUCtl <=0; // and 37: ALUCtl <=1; // or 39: ALUCtl <=12; // nor 42: ALUCtl <=7; // slt default: ALUCtl <=15; // should not happen endcase endmodule

A Register File
A register file consists of a set of registers that can be read and written by supplying a register number to be accessed. The read ports cab be implemented with a pair of multiplexors. The write port can be implemented with a decoder

The implementation of two read ports for a register file with n registers can be done with a pair of n-to-1 multiplexors each 32 bits wide.

The write port for a register file is implemented with a decoder that is used with the write signal to generate the C input to the registers.

A MIPS register file written in behavioral Verilog


This register file writes on the rising clock edge. module registerfile (Read1,Read2,WriteReg,WriteData, RegWrite,Data1,Data2,clock); input [5:0] Read1,Read2,WriteReg; // the registers numbers to read or write input [31:0] WriteData; // data to write input RegWrite, // The write control clock; // the clock to trigger write output [31:0] Data1, Data2; // the register values read reg [31:0] RF [31:0]; // 32 registers array each 32 bits long assign Data1 = RF[Read1]; assign Data2 = RF[Read2]; always begin // write the register with new value if Regwrite is high @(posedge clock) if (RegWrite) RF[WriteReg] <= WriteData; end endmodule

Using a Hardware Description Language to Design and Simulate a Processor


The below Verilog example gives a behavioral specification of the multicycle implementation of the MIPS processor. This version does not use the structural datapath. Because of the use of behavioral operations, it would be difficult to synthesize a separate datapath and control unit with any reasonable efficiency. This version also demonstrates another approach to the control by using a Mealy finite state machine.The use of a Mealy machine, which allows the output to depend both on inputs and the current state, allow us to decrease the total number of states to 5.

A behavioral specification of the multicycle MIPS design


module CPU (clock); parameter LW = 6'b100011, SW = 6'b101011, BEQ=6'b000100, J=6d2; input clock; //the clock is an external input
// The architecturally visible registers and scratch registers for implementation

reg [31:0] PC, Regs[0:31], Memory [0:1023], IR, ALUOut, MDR, A, B; reg [2:0] state; // processor state wire [5:0] opcode; //use to get opcode easily wire [31:0] SignExtend,PCOffset; //used to get sign extended offset field assign opcode = IR[31:26]; //opcode is upper 6 bits
//sign extension of lower 16-bits of instruction

assign SignExtend = {{16{IR[15]}},IR[15:0]}; assign PCOffset = SignExtend << 2; //PC offset is shifted

The state machine--triggered on a rising clock


// set the PC to 0 and start the control in state 0
initial begin PC = 0; state = 1; end

always @(posedge clock) begin //make R0 0 //short-cut way to make sure R0 is always 0 Regs[0] = 0; case (state) //action depends on the state

First step: fetch the instruction, increment PC, go to next state


1: begin IR <= Memory[PC>>2]; PC <= PC + 4; state=2; //next state end

Second step: Instruction decode, register fetch, also compute branch address
2: begin A <= Regs[IR[25:21]]; B <= Regs[IR[20:16]]; state= 3; // compute PC-relative branch target ALUOut <= PC + PCOffset; end

Third step: Load/store execution, ALU execution, Branch completion


3: begin state =4; // default next state if ((opcode==LW) |(opcode==SW)) ALUOut <= A + SignExtend; //compute effective address else if (opcode==6'b0) case (IR[5:0]) //case for the various R-type instructions 32: ALUOut= A + B; //add operation default: ALUOut= A; //other R-type operations: subtract, SLT, etc. Endcase else if (opcode == BEQ) begin if (A==B) PC <= ALUOut; // branch taken--update PC state = 1; end else if (opocde=J) begin PC = {PC[31:28], IR[25:0],2'b00}; // the jump target PC state = 1; end //Jumps else ; // other opcodes or exception for undefined instruction would go here end

Four step: Write ALU result, Read/write the memory


4: begin if (opcode==6'b0) begin //ALU Operation Regs[IR[15:11]] <= ALUOut; // write the result state =1; end //R-type finishes else if (opcode == LW) begin // load instruction MDR <= Memory[ALUOut>>2]; // read the memory state =5; // next state end else if (opcode == SW) begin Memory[ALUOut>>2] <= B; // write the memory state = 1; // return to state 1 end //store finishes else ; // other instructions go here end

Five step: LW is the only instruction still in execution


5: begin // write the MDR to the register Regs[IR[20:16]] = MDR; state = 1; end //complete a LW instruction endcase end endmodule

Questions?

You might also like