Skip to main content

RTL Design Engineer at Skyroot Aerospace

Hello, Dear Readers, Skyroot Aerospace has a vacancy for the RTL Design Engineer role. About Skyroot Aerospace: A cutting-edge startup founded by ex-ISRO scientists. Dedicated to affordable space access, we're rewriting aerospace technology rules. Our dynamic team fosters inventiveness, collaboration, and relentless excellence. Join us on a transformative journey to redefine space possibilities. Welcome to the forefront of space innovation with Skyroot Aerospace! Purpose of role: Understand architectural requirements and Design micro-architecture, implement design blocks using VHDL/Verilog for FPGA based Avionics packages for orbital launch vehicles and ground infrastructure. Job Requirements: 2+ Years of RTL and system design experience. Strong knowledge on Digital System Design (DSD). Strong knowledge of RTL/SoC design/integration with VHDL/Verilog. Strong knowledge in problem solving and debugging skills. Ability to understand architectural requirements and Design micro-archite...

Design of the 3 Stage Pipeline Microprocessor Using Verilog

 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 


Simulational Results:
















Comments

  1. Wow great post keep it up

    ReplyDelete
  2. It is Hazards free code such WAW,RAW hazards etc...

    ReplyDelete
    Replies
    1. Yes I have solved RAW hazards which is most important and WAW hazards solve because it is inline pipeline.

      Delete
  3. Wow 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?

    ReplyDelete
    Replies
    1. Yes basically pipeline means always block is key block and in hardware wise it is register in between two pipeline.

      Delete
  4. When you put RISC-V processor verilog code please bro I have try lots but not understand.

    ReplyDelete
  5. i have used the code but i am not getting proper waveform i am getting clk and rst as z

    ReplyDelete

Post a Comment

Popular posts from this blog

Internship - SoC /IP Design at NXP India

Hello Dear Readers, Currently, at NXP India  vacancy for  Internship - SoC /IP Design   role.   We are looking for a Master degree student with Electronics and Communication Engineering, or related field, with an emphasis on SoC design. This is a full-time internship with a duration of about 11-12 months. Job Responsibility: Working with our experienced design team to design state of the art SoC hardware specific segment applications like Automotive, IoT, voice/object recognition, security, smart connectivity and touch sensing . Assisting experienced engineers with End-to-end ownership of SoC Design, Verification and implementation (Physical Design). Design and verify digital and Mixed-signal IPs. Document designs and present results. Job Qualification: Master student in electronic/computer engineering Creative and positive mindset Good knowledge on CMOS technologies Great communication skills, interpersonal skills, teamwork skills and can-do attitude Desire for a ca...

Exploring the Role of LEF Files in VLSI Chip Design: A Beginner's Guide

Hello Dear Readers,   Today in this post, I will provide some deep insight into the LEF file role during the VLSI Chip Design process. In VLSI (Very Large Scale Integration) design, a LEF file is a file that contains information about the physical geometry of the standard cells used in a circuit. LEF stands for Library Exchange Format. A standard cell is a pre-designed logic cell that contains a specific function, such as a flip-flop or an AND gate. Standard cells are designed to be easily combinable and scalable to create more complex circuits. The physical geometry of each standard cell is defined in the LEF file. The LEF file contains information such as the width, height, and position of the pins and metal layers of each standard cell. It also contains information about the physical design rules that govern the placement of these cells on the chip. LEF files are important in VLSI design because they enable the interoperability of different design tools from different vend...

Best Book for Designing Microarchitecture of Microprocessor Using Verilog HDL

  Hello Dear Readers, Currently, after succeeding in many topics now I starting to provide technical book reviews which were I have completed and still read books always. So let us start today's book review. Book Name:   Computer Principles and Design in Verilog  HDL Description:  Uses Verilog HDL to illustrate computer architecture and microprocessor design, allowing readers to readily simulate and adjust the operation of each design, and thus build industrially relevant skills Introduces the computer principles, computer design, and how to use Verilog HDL (Hardware Description Language) to implement the design Provides the skills for designing processor/arithmetic/cpu chips, including the unique application of Verilog HDL material for CPU (central processing unit) implementation Despite the many books on Verilog and computer architecture and microprocessor design, few, if any, use Verilog as a key tool in helping a student to understand these design techniques...