Hello Dear Readers, Cadence Design Systems has a vacancy for a Product Engineer II role. Cadence is a pivotal leader in electronic design, building upon more than 30 years of computational software expertise. The company applies its underlying Intelligent System Design strategy to deliver software, hardware and IP that turn design concepts into reality. Cadence customers are the world’s most innovative companies, delivering extraordinary electronic products from chips to boards to systems for the most dynamic market applications including consumer, hyperscale computing, 5G communications, automotive, aerospace industrial and health. The Cadence Advantage: The opportunity to work on cutting-edge technology in an environment that encourages you to be creative, innovative, and to make an impact. Cadence’s employee-friendly policies focus on the physical and mental well-being of employees, career development, providing opportunities for learning, and celebrating success in recog...
Hello Dear Readers,
First of all thanks for giving motivation on my first of designing microprocessor. DESIGN OF THE SINGLE CYCLE MICROPROCESSOR USING VERILOG HDL. So now in this post, i will explain the 3 stages of the pipeline microprocessors namely the Fetch Unit, Decode Unit, and Execute Unit. So Let's start designing based on the specification given below.
Stage-1: Fetch Unit
Fetch Unit comprises half-word addressable instruction memory. It takes
PC as input and gives the instruction as an output. PC is also incremented by
PC=PC+1.
Stage-2: Decode Unit
Decode Unit reads the fetched instruction and decodes the address of two
source operands and destination register. Also, it generates the immediate data.
Register Bank reads the value of source operands (Rs1 and Rs2) at negative
level of the clock, and writes the data in the destination register (Rd) at positive
level of clock.
Control Unit uses 4-bit opcode bits to determine the type of instruction.
Stage-3: Execute Unit
ALU Control Unit uses the type of instruction generated by control unit, and
generates a 2-bit ALUOP (ALU Operation) signal.
ALU Module uses the ALUOP generated by ALU Control Unit to perform
the operation on source operands.
Write Back Unit using the type of instruction from control unit write the
output data from ALU module in the destination register of the register bank.
Instruction Format:
OPCODE
R-type = 4’d1
I-type = 4’d2
Func3
ADD and ADDI=3’d0
SUB and SUBI=3’d1
AND and ANDI=3’d2
OR and ORI=3’d3
So now Start coding,
Verilog Code:
FETCH UNIT:
module fetchInstruction(
input clk,
input rst,
output reg [15:0] prog_ctr,
output reg [15:0] curr_instr
);
reg [7:0] instr [255:0];
initial begin
prog_ctr = 16'b0;
curr_instr = 16'b0;
$readmemh("instruction_memory.txt",instr);
end
always @(posedge rst) begin
prog_ctr = 16'b0;
curr_instr = 16'b0;
end
always @(posedge clk) begin
curr_instr[7:0] = instr[prog_ctr[15:0]];
prog_ctr = prog_ctr+1;
curr_instr[15:8] = instr[prog_ctr[15:0]];
prog_ctr = prog_ctr+1;
end
endmodule
The next instruction is fetched from the memory address that is currently stored in the program
counter and stored in the instruction register. At the end of the fetch operation, the PC points to the
next instruction that will be read at the next cycle.
DECODE AND CONTROL UNIT:
module decode_control_unit(
input clk,rst,inuse1,inuse2,
// input from the fetch unit
input [15:0] curr_instr,
// input provided from the register bank
input[15:0] srcRegVal1,srcRegVal2,
output reg [2:0] srcReg1,
output reg [2:0] srcReg2,
output reg [2:0] nextDestReg,
output reg [3:0] opcode,
output reg[2:0] destReg,
output reg[15:0] srcVal1,srcVal2,
output reg used1,used2,
output reg [1:0] alu_control,
output reg [1:0] control_op
);
initial begin
srcReg1 = 3'b0;
srcReg2 = 3'b0;
nextDestReg = 3'b0;
opcode = 4'b0;
destReg =3'b0;
srcVal1 =16'b0;
srcVal2 =16'b0;
used1 =0;
used2 =0;
alu_control=2'b0;
control_op=2'b0;
end
always @(posedge rst) begin
#2
srcReg1 = 3'b0;
srcReg2 = 3'b0;
nextDestReg = 3'b0;
opcode = 4'b0;
destReg = 3'b0;
srcVal1 = 16'b0;
srcVal2 = 16'b0;
used1 = 0;
used2 = 0;
alu_control = 2'b0;
control_op =2'b0;
end
always @(posedge clk) begin
opcode = curr_instr[3:0];
nextDestReg = curr_instr[6:4];
destReg = curr_instr[6:4];
srcReg1 = curr_instr[12:10];
srcReg2 = curr_instr[9:7];
alu_control = curr_instr[14:13];
end
always @(srcRegVal1 or srcRegVal2 or inuse1 or inuse2) begin
srcVal1 = srcRegVal1;
srcVal2 = srcRegVal2;
used1 = inuse1;
used2 = inuse2;
control_op =alu_control[1:0];
end
endmodule
During this stage, the encoded instruction presented in the instruction register is interpreted by the
decoder. In the case of a memory instruction, the execution phase will be during the next clock pulse.
If the instruction has an indirect address, the effective address is read from the main memory, and any
required data is fetched from main memory to be processed and then placed into data registers. If the
instruction is direct, nothing is done during this clock pulse. If this is an I/O instruction or a register
instruction, the operation is performed during the clock pulse.
REGISTER UNIT:
module Register_bank(
input clk,
input rst,
input[2:0] srcReg1,
input[2:0] srcReg2,
input[2:0] nextDestReg,
input [3:0] opcode,
input[2:0] destReg,
input[15:0] destVal,
input storeNow,
output reg storeDone,
output reg [15:0] srcRegVal1,srcRegVal2,
output reg inuse1,inuse2
);
reg [15:0] ime_data[7:0];
// Array of Registers
reg[15:0] r[7:0];
reg inuse[7:0];
/*
For loop initialization
*/
integer i;
/*
Initialize all registers and inuse bits to 0.
*/
initial begin
for(i=0; i<8; i=i+1) begin
r[i] = 16'b0;
inuse[i]=1'b0;
end
r[2]=16'd1;
r[1]=16'd10;
r[0]=16'd4;
r[5]=16'd5;
r[6]=16'd8;
srcRegVal1 = 16'b0;
srcRegVal2 = 16'b0;
inuse1 = 0;
inuse2 = 0;
storeDone = 0;
#2
$display(" a=0x%0h b=0x%0h",r[2],r[3]);
end
/*
Initialize all registers and inuse bits to 0 on reset.
*/
always @(posedge rst) begin
for(i=0; i<8; i=i+1) begin
r[i] = 16'b0;
inuse[i] = 1'b0;
end
srcRegVal1 = 16'b0;
srcRegVal2 = 16'b0;
inuse1 = 0;
inuse2 = 0;
storeDone = 0;
end
/*
When any input changes, recompute outputs for 'Decode & Fetch Operand' stage
*/
always @(clk or srcReg1 or srcReg2 or nextDestReg or opcode) begin
if(opcode == 4'b0001) begin
srcRegVal1 = r[srcReg1];
srcRegVal2 = r[srcReg2];
inuse1 = inuse[srcReg1];
inuse2 = inuse[srcReg2];
end
if(opcode == 4'b0010) begin
srcRegVal1 = ime_data[srcReg1];
srcRegVal2 = r[srcReg2];
inuse2 = inuse[srcReg2];
end
end
/*
Set inuse at posedge
*/
always @(posedge clk) begin
for(i=0;i<8;i=i+1)
inuse[i] = 1'b0;
inuse[nextDestReg] = 1'b1;
end
always @(posedge storeNow) begin
storeDone = 0;
r[destReg] = destVal;
storeDone = 1;
end
endmodule
The register file is a register bank that holds the data required for performing operations
and also stores their result after execution.
EXECUTE AND WRITE BACK STAGE:
module execute_store(
input clk,rst,used1,used2,storeDone,
input [1:0] control_op,
input [2:0] destReg,
input [15:0] srcVal1,
input [15:0] srcVal2,
output reg [2:0] destRegStore,
output reg [15:0] destVal,
output reg storeNow,
output reg powerdown
);
reg [15:0] LastComputedValue,val1,val2;
initial begin
destRegStore =3'b0;
destVal =16'b0;
LastComputedValue =16'b0;
storeNow =0;
val1 =16'b0;
val2 =16'b0;
powerdown =0;
end
always @(posedge rst) begin
destRegStore = 3'b0;
destVal = 16'b0;
LastComputedValue = 16'b0;
storeNow = 0;
val1 = 16'b0;
val2 = 16'b0;
end
always @(posedge clk) begin
storeNow = 0;
#1 if(used1)
val1 = LastComputedValue;
else
val1 = srcVal1;
if(used2)
val2 = LastComputedValue;
else
val2 = srcVal2;
#1 case(control_op)
2'b00:begin
destVal = val1 + val2;
end
2'b01:begin
destVal = val1 - val2;
end
2'b10:begin
destVal = val1 & val2;
end
2'b11:begin
destVal = val1 | val2;
end
default: begin
powerdown = 1;
end
endcase
destRegStore = destReg;
storeNow = 1;
#1 LastComputedValue = destVal;
end
endmodule
The control unit of the CPU passes the decoded information as a sequence of control signals to the
relevant function units of the CPU to perform the actions required by the instruction, such as reading
values from registers, passing them to the ALU to perform mathematical or logic functions on them,
and writing the result back to a register. If the ALU is involved, it sends a condition signal back to the
CU. The result generated by the operation is stored in the main memory or sent to an output device.
Based on the feedback from the ALU, the PC may be updated to a different address from which the
next instruction will be fetched.
MAIN MODULE:
module verilog_code(
input clk,rest,
output powerdown,
output [15:0] prog_ctr
);
reg [7:0] instr [255:0];
reg [15:0] ime_data[7:0];
wire[15:0]curr_instr,srcRegVal1,srcRegVal2,srcVal1,srcVal2,destVal;
wire[2:0] srcReg1,srcReg2,destReg,nextDestReg;
wire [3:0] opcode;
wire [1:0] alu_control,control_op;
initial begin
$readmemh("data_memory.txt",ime_data);
$readmemh("instruction_memory.txt",instr);
end
// Fetch stage
fetchInstruction I(clk,rst,prog_ctr,curr_instr);
// Decode stage
decode_control_unit
D(clk,rst,inuse1,inuse2,curr_instr,srcRegVal1,srcRegVal2,
srcReg1,srcReg2,nextDestReg,opcode,destReg,srcVal1,srcVal2,used1,used2,alu_control,control_op);
// Register File
Register_bank R(clk,rst,
srcReg1,srcReg2,nextDestReg,opcode,
destReg,destVal,storeNow,storeDone,
srcRegVal1,srcRegVal2,inuse1,inuse2);
// Execute Stage
execute_store E(clk,rst,used1,used2,storeDone,alu_control,destReg,srcVal1,srcVal2,destRegStore,destVal,storeNow,powerdown);
endmodule
Wow great post keep it up
ReplyDeleteIt is Hazards free code such WAW,RAW hazards etc...
ReplyDeleteYes I have solved RAW hazards which is most important and WAW hazards solve because it is inline pipeline.
DeleteWow bro I have used it for my project of 5 stage pipeline actually pipeline means logic of always block only or any other for whole thing?
ReplyDeleteYes basically pipeline means always block is key block and in hardware wise it is register in between two pipeline.
DeleteWhen you put RISC-V processor verilog code please bro I have try lots but not understand.
ReplyDeletei have used the code but i am not getting proper waveform i am getting clk and rst as z
ReplyDelete