← Back to list

Simple 8-bit Processor Design and Verilog implementation (Part 2)

Hi, In this article we will continue from where we left off in part1. We have already designed the ALU model and Register model which…

Sathira Basnayake · 2021-07-15 19:29 · 395 claps · 5.2 min read
#verilogy #hardware-designer #assembly #enjoy-writing #tech
Open on Medium ↗
Wiki topics: DSN · Design · General

Simple 8-bit Processor Design and Verilog implementation (Part 2)

Hi, In this article we will continue from where we left off in part1. We have already designed the ALU model and Register model which supports add, sub, and, or, mov and loadi instructions. Now what we should do is compose a working CPU using the above models. And in this article, I will show you how to implement the instruction fetching mechanism and a program counter register that points to the next instruction. We will implement all control logic in our CPU top-level module itself.

module cpu(PC,INSTRUCTION,CLK,RESET)

As we are not implementing a memory module we will keep the instruction as an array of hardcoded instruction words (1024 bytes / 256 instructions) in the testbench file which we use to test your CPU. We will read the instruction asynchronously, based on the address provided by the PC.

To implement this we need a combination logic to decode a fetch instruction, extract the op-code, source or destination registers immediate values. We should generate all the control signals and send them to the register file, alu, and other components appropriately. We should do this according to the op-code. Bits 25:0 need to be simply sent to appropriate places where they may be used.

We have to pay close attention to how to coordinate the timing in instruction fetching, execution, and register file reading/writing. To realistically simulate the lateness of instruction fetching and decoding. To ensure that we will add these artificial timing delays in our design.

  • Instruction Decode = One time unit (#1)
  • PC Update = One time unit (#1)
  • Instruction Memory Read = Two time units (#2)

We will start with something simple. We know that to fetch the next instruction we have to increment the PC value by 4 . To that we will implement a dedicated adder. What this will do is simply increment the PC value

//this adder is to increment pc value with 4
module adder(PCINPUT,RESULT);
 input [31:0] PCINPUT;
 output [31:0] RESULT;
 reg RESULT;
 always@(PCINPUT)
 begin
  RESULT = PCINPUT+ 4;
 end
endmodule

I will show you a full overview of the CPU. In this diagram, we can get a full understand of the CPU.

Overview of the CPU

Overview of the CPU

Next, we will talk about the timing of the CPU. we will make one clock span for a ten-time duration, rising edge to rising edge. In this case, every instruction should complete within one clock cycle. The next important part is every value to be written into registers should be ready by the rising edge. We should synchronous writing to registers and risings edge of the clock. To make our task simple we should add artificial delays to the corresponding operations for stimulation purposes. We will assume that our multiplexers and 2’s complement unit have negligible wires.

Timing Details

Timing Details

When we implementing the reset module if the reset signal is high when writing to PC at a positive clock edge, write -4 to PC instead of the next PC value in order to restart the program.

This is the code for the CPU module

module cpu(PC,INSTRUCTION,CLK,RESET);
 input [31:0] INSTRUCTION;

 input CLK;
 input RESET;
output [31:0] PC;
reg [31:0] PC;
 wire [31:0] PCRESULT;
reg writeEnable;
    reg isAdd;
    reg isImediate;
    reg [2:0] aluOp;
    reg [2:0] regRead1Addres;
    reg [2:0] regRead2Addres;
    reg [2:0] writeRegAddres;
    reg [7:0] immediateVal;
    wire [7:0] mux1out;
    wire [7:0] mux2out;
    wire [7:0] ALURESULT;
    wire [7:0] minusVal;
reg [7:0] IN;
    wire [7:0] OUT1;
    wire [7:0] OUT2;
reg [7:0] OPCODE; 
    reg [2:0] DESTINATION;  
    reg [2:0] SOURCE1; 
    reg [2:0] SOURCE2;
always@(RESET)
    //reseting the pc if reset is on
    begin
     if(RESET ==1)  PC =-4;

    end
//adder to update pc from 4
    adder myadder(PC,PCRESULT);
    always@(posedge CLK)
    begin
       #1
       PC = PCRESULT;
    end

    always @(INSTRUCTION)
 begin
     // taking the opcode from the instruction
     OPCODE = INSTRUCTION[31:24];
     #1
     //decodeing the opcode
  case(OPCODE)
   8'b00000000:
       begin
    writeEnable = 1'b1;
    aluOp = 3'b000;
    isAdd = 1'b1;
    isImediate = 1'b1;
    end
   8'b00000001:
       begin
    writeEnable = 1'b1;  
    aluOp = 3'b000;
    isAdd = 1'b1;
    isImediate = 1'b0;
    end
   8'b00000010:
       begin
    writeEnable = 1'b1;
    aluOp = 3'b001;
    isAdd = 1'b1;
    isImediate = 1'b0;
    end
   8'b00000011:
       begin
    writeEnable = 1'b1;
    aluOp = 3'b001;
    isAdd = 1'b0;
    isImediate = 1'b0;
    end
   8'b00000100:
       begin
    writeEnable = 1'b1;
    aluOp = 3'b010;
    isAdd = 1'b1;
    isImediate = 1'b0; 
    end
   8'b00000101:
       begin
    writeEnable = 1'b1;
    aluOp = 3'b011;
    isAdd  =1'b1;
    isImediate = 1'b0; 
    end     

  endcase        
 end
 //including the register file
    reg_file myReg(IN,OUT1,OUT2,DESTINATION,SOURCE1,SOURCE2,writeEnable,CLK,RESET);
 always@(INSTRUCTION)
 begin
     DESTINATION  = INSTRUCTION[18:16];
      SOURCE1   = INSTRUCTION[10:8];
     SOURCE2 = INSTRUCTION[2:0];
     immediateVal =INSTRUCTION[7:0];
 end
 //this is two's complemebt unit to substraction
 twosCompliment mytwo(OUT2,minusVal);
//multiplexer to choose between minus value and plus value
 mux2_1 mymux1(OUT2,minusVal,isAdd,mux1out);

 //multiplexer to chose between immediate value and mux1 output
 mux2_1 mymux2(immediateVal,mux1out,isImediate,mux2out);

    //allu module
    alu myalu(OUT1,mux2out,ALURESULT,aluOp);
    always@(ALURESULT)
 begin
    IN =ALURESULT;  //setting the reg input with the alu result
 end
endmodule

This is the implementation of the multiplexer and the two’s complement modules.

//this is a implementation of a 2 to 1 multiplexer
module mux2_1(in0,in1,se1,out);
 input se1;      //immediae value
 input [7:0] in0; 
 input [7:0] in1;           // register output
 output [7:0] out;
 reg out;
always @(in0,in1,se1)
 begin
  if(se1==1'b1) begin
   out =in0;
  end 
  else 
  begin
   out =in1;
  end
 end    
endmodule
//this is used to convert numbers into minus in two's complement
module twosCompliment(in,result);
   input [7:0] in;
   output [7:0] result;
   reg result;
   always@(*) 
   begin
       result = ~in+1;
   end
endmodule

Now we have to create an appropriate test bench to test our code. As we don’t have a memory module we have to hard code the instructions in our test bench.

This is the sample test bench. I have written some machine code and hard code them into this test bench.

Congratulations! we have implemented our simple 8-bit processor. We should thoroughly test our CPU with different combinations of instructions. To make instructions we have to have good knowledge about our instruction set architecture. We have to convert assembly code into machine code.

sub 3 4 3

when we convert the above assembly code into machine code it is 32'b00000111111110110000001000000001. Likewise, we have to generate machine codes and add them to the test bench. To run this code we can use Icarus Verilog as the tool. You can find tutorials on how to download and run the tool. This machine code is generated according to the bits we allocated at the beginning of part1. If you haven’t read it, please read it first. And if you have any questions please leave a comment.

Thank You all.

Feel like you’re about to jump into a rabbit-hole of reading these incredible articles? Don’t worry, we feel the same way. Not only can you jump into the rabbit hole with us, but we’ve got more than enough articles that’ll help you jump out ;) For some of the best ideas on Medium from the youngest minds of the generation, visit students x students.

[embed]students x students Providing a platform to uplift student voices and give them greater confidence and fulfillment in their writing.studentsxstudents.com


메타데이터
post_id
f1465be2cbe2
slug
simple-8-bit-processor-design-and-verilog-implementation-part-2-f1465be2cbe2
url
https://medium.com/@sathira97/simple-8-bit-processor-design-and-verilog-implementation-part-2-f1465be2cbe2
canonical_url
https://medium.com/@sathira97/simple-8-bit-processor-design-and-verilog-implementation-part-2-f1465be2cbe2
author_url
https://medium.com/@sathira97
status
ok
fetched_at
2026-06-26 12:24:55