Verilog Code for 16bit RISC Processor


16BIT RISC PROCESSOR

Hola Amigos
I have designed a 16bit RISC processor designed with Xilinx iSim ans iSim simulator. RISC stands for Reduced Instruction Set Computer which is small microprocessor designed to favour small tasks and compute instructions with less time for the execution process. 
Common RISC processors that you would see around are ARM, MIPS, IBM Pc. 

Why was RISC introduced ?
As compared with CISC (Complex Instruction Set Computer) which takes a complex time to execute the instructions was reducing the performance of computing where the speed was drowning when CPU contacts the data memory. Hence another alternative was set in motion and that was RISC architecture.

Coming down to my 16bit processor.
ALU  Code-
**************************************************************************************

module ALU(ain,bin,func,result,z);
input [7:0]ain;
input [7:0]bin;
output reg[7:0]result;
reg carry,temp=0;
input [3:0]func;
output reg z;
//wire [7:0]result;
//assign n = result[7];
always @(ain or bin)begin
if(func==4'b0000)begin
{temp,result} = ain + bin;
carry = temp;
if(result==0)
z=1;
end
else if(func==4'b0001)begin
{temp,result} = ain - bin;
carry = temp;
if(result==0)
z=1;
end
else if(func==4'b0010)begin
{temp,result} = ain + 1;
carry = temp;
if(result==0)
z=1;
end
else if(func==4'b0011)begin
{temp,result} = ain - 1;
carry = temp;
if(result==0)
z=1;
end
else if(func==4'b0100)begin
result = ain | bin;
carry = 0;
if(result==0)
z=1;end //OR
else if(func==4'b0101)begin 
result = ain & bin;
carry = 0;
if(result==0)
z=1;end //AND
else if(func==4'b0110)begin 
result = ain^bin;
carry = 0;
if(result==0)
z=1;end //XOR
else if(func==4'b0111)begin 
result[0] = ~(ain[0]&bin[0]);
result[1] = ~(ain[1]&bin[1]);
result[2] = ~(ain[2]&bin[2]);
result[3] = ~(ain[3]&bin[3]);
result[4] = ~(ain[4]&bin[4]);
result[5] = ~(ain[5]&bin[5]);
result[6] = ~(ain[6]&bin[6]);
result[7] = ~(ain[7]&bin[7]);
carry = 0;
if(result==0)
z=1;end //NAND
else if(func==4'b1000)begin 
result[0] = ~ain[0];
result[1] = ~ain[1];
result[2] = ~ain[2];
result[3] = ~ain[3];
result[4] = ~ain[4];
result[5] = ~ain[5];
result[6] = ~ain[6];
result[7] = ~ain[7];
carry = 0;
if(result==0)
z=1;end //NOT
else begin 
result = 4'bxxxx;
carry = 0;
end //Default
if(result==0)
z = 1'b1;
else
z = 0;
end

endmodule

Instruction Memory
**************************************************************************************
module instruction(address,clk,opcode,jump,jiz,addA,addB,write_add,iformat,im_select);
input [15:0]address;
input clk,im_select;
output reg[3:0]opcode;
output reg[11:0] jump;
output reg[7:0] jiz;
output reg[3:0] addA;
output reg[3:0] addB;
output reg[3:0] write_add;
output reg[3:0] iformat;
reg [3:0]dest;
reg [15:0]instruction;
reg [15:0] imem[0:15];
initial begin
imem[2]<=16'b0000_0000_0000_0101; 
imem[1]<=16'b0001_0010_0011_0011; 
imem[3]<=16'b0010_0100_0010_0011;
imem[0]<=16'b0010_0000_0000_0101;
imem[4]<=16'b0010_0111_0010_0011;
imem[5]<=16'b0011_0010_0011_0010;
imem[6]<=16'b0110_0001_0001_0011;
imem[7]<=16'b0001_0110_0001_0011;
imem[8]<=16'b0110_0001_0011_0001; 
end
always @(im_select)begin
if(im_select==1)begin
dest=write_add;
instruction = imem[address];
opcode = instruction[15:12];
jump = instruction[11:0];
jiz = instruction[7:0];
addA = instruction[11:8];
addB = instruction[7:4];
write_add = instruction[3:0];
iformat = instruction[3:0];
end
end

endmodule

Register File
**************************************************************************************
module Register(reg_wrt,readA,clk,readB,dest,data,readA_out,readB_out);
input reg_wrt;
input [3:0]readA,readB,dest;
input [7:0]data;
input clk;
reg [7:0] Register [0:15];
initial begin
Register[0]=0;//R0 alwayscontains zero
Register[1]=2;  //Random values stored
Register[2]=4;
Register[3]=6;
Register[4]=8;
Register[5]=10; // You can change any value within this initial block
Register[6]=12;
Register[7]=14;
end
output reg [7:0]readA_out,readB_out;
always @(posedge clk)begin
readA_out <= Register[readA];
readB_out <= Register[readB];
if(reg_wrt==1)
Register[dest]=data;
end

endmodule

RAM (Datamemory) 
**************************************************************************************
module RAM(address,clk,data_in,data_out,re,wr);
input [7:0]address;
input [7:0]data_in;
input clk,re,wr;
output [7:0]data_out;
reg[7:0] mem [0:30];
reg[7:0] data;
assign data_out = data;
initial
mem[16]=25;
always @(posedge clk)begin
if(wr)begin
mem[address] = data_in;
end
end
always @(address or re)begin
if(re)begin
data = mem[address];
end
end

endmodule

Program Counter
**************************************************************************************
module PC(in,clk,out,pc_sel,reset);
input [15:0]in;
input clk,reset,pc_sel;
output reg[15:0]out;
initial 
out = 0;
always @(posedge clk)begin
if(reset==1)
out <= 16'bx;
else if(pc_sel==1 && in<50)
out <= in+1;
else if(pc_sel==0)
out <= in;
end

endmodule

Multiplexers
**************************************************************************************

module Mux1(a,b,sel,c);

input [3:0] a,b;

input sel;

output reg [3:0]c;

always @(*)begin

if(sel==0)

c = a;

else

c = b;

end

endmodule

module Mux2(a,b,sel,c);
input [7:0] a,b;
input [1:0]sel;
output reg [7:0]c;
always @(*)begin
if(sel==2'b0)
c = a;
else if(sel==2'b01)
c = b;
else if(sel==2'b10)
c = 8'b0;
end
endmodule

module Mux3(a,b,sel,c);
input [15:0] a,b;
input sel;
output reg [15:0]c;
always @(*)begin
if(sel==0)
c = a;
else
c = b;
end
endmodule

Sign Extend
**************************************************************************************
module sign(a,b);
input [3:0]a;
output reg[7:0]b;
always @(a or b)begin
if(a[3]==1)
b = {4'b1111,a};
else
b = {4'b0000,a};
end
endmodule

Latch
**************************************************************************************
module lat(in,out,clk);
input [7:0] in;
input clk;
output reg[7:0] out;
reg [7:0]memdataout;
always @ (posedge clk)
out=in;
endmodule

Datapath
**************************************************************************************
module datapath(alu_op,opcode,clk,carry,sel1,sel2,sel3,sel5,sel6,re,wr,reg_wrt,reset,pc_sel,im_select,branch);
input clk;
output carry;
input [1:0]sel2;
input sel1,sel3,sel5,sel6,re,wr;
input reg_wrt;
input reset;
output [3:0]opcode;
input [3:0]alu_op;
input im_select;
input branch,pc_sel;
wire [7:0] shift;
wire [15:0] next_pc;
wire [15:0] next_alu_out,jump_add;
wire [11:0] jump;
and (sel4,branch,zero);
wire [15:0]op3,out;
wire [15:0]pc_out;
wire [3:0]iformat,addA,addB,write_add,out1;
wire [7:0]data_out;
wire [7:0]result;
wire [7:0]regData,aluMux;
wire [7:0] dataA,dataB,xtended,out2,latchout;
Mux2 alu(dataA,8'bx,sel5,aluMux);
PC programcounter(op3,clk,pc_out,pc_sel,reset);
instruction im(pc_out,clk,opcode,jump,addA,addB,write_add,iformat,pc_sel);
Mux1 multi1(addB,write_add,sel1,out1);
Register regfile(reg_wrt,addA,clk,addB,out1,regData,dataA,dataB);
sign xtend(iformat,xtended);
lat latch(xtended,latchout,clk);
Mux2 multi2(dataB,latchout,sel2,out2);
ALU alux(aluMux,out2,alu_op,result,zero);
RAM datamemory(result,clk,dataB,data_out,re,wr);
Mux2 multi3(result,data_out,sel3,regData);
//assign next_pc = pc_out+1'b1;
assign next_alu_out = latchout + pc_out;
assign jump_add = {pc_out[15:12],jump}; 
Mux3 multi4(pc_out,next_alu_out,sel4,out);
Mux3 multi5(jump_add,out,sel6,op3);
endmodule

Control Unit
**************************************************************************************
module control(alu_op,opcode,clk,carry,reset,reg_wrt,re,wr,Mux1,Mux2,Mux3,MuxAlu,Mux5,branch,pc_sel,im_select);
input clk,carry,reset;
input [3:0] opcode;
output reg[3:0]alu_op;
output reg reg_wrt,re,wr,Mux1,Mux3,MuxAlu,Mux5,branch,pc_sel,im_select;
output reg[1:0]Mux2;
reg [3:0]pstate,nstate;
parameter s0 = 4'b0000,s1 = 4'b0001, s2=4'b0010, s3=4'b0011, s4=4'b0100, s5=4'b0101, s6=4'b0110, s7=4'b0111, s11=4'b1000;
initial
pstate = s0;
always @(posedge clk)begin
case(pstate)
//*********************************************************************************************************************
s0:begin  //DO NOT MODIFY INSTRUCTION FETCH  //
reg_wrt<=1'b0;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b0;
Mux2<=1'b1;
Mux3<=1'b0;
Mux3<=1'b1;
Mux5<=1'b1;
alu_op<=4'bxxxx;
MuxAlu<=1'b1;
branch<=1'b0;
pc_sel<=1'b1;
im_select<=1'b1;
pstate<=s1;
end
//*********************************************************************************************************************
s1:begin  // DO NOT MODIFY DECODE STAGE  //
case(opcode)
4'b0000:begin
alu_op<=4'b0;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=1'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//*********************************************************************************************************************
4'b0001:begin  /* DO NOT MODIFY R-FORMAT STARTS HERE */
alu_op<=4'b0001;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//*********************************************************************************************************************
4'b0010:begin
alu_op<=4'b0010;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//*********************************************************************************************************************
4'b0011:begin
alu_op<=4'b0011;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//*********************************************************************************************************************
4'b0100:begin
alu_op<=4'b0100;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//*********************************************************************************************************************
4'b0101:begin
alu_op<=4'b0101;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//*********************************************************************************************************************
4'b0110:begin
alu_op<=4'b0110;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//*********************************************************************************************************************
4'b0111:begin
alu_op<=4'b0111;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//*********************************************************************************************************************
4'b1000:begin
alu_op<=4'b1000;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b0;
pstate<=s0;
end
//*********************************************************************************************************************
4'b1001:begin
alu_op<=4'b1001;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b0;
pstate<=s0;
end
//*********************************************************************************************************************
4'b1010:begin
alu_op<=4'b1010;
reg_wrt<=1'b1;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b0;
pstate<=s0;
end   /* DO NOT MODIFY R-FORMAT ENDS HERE */
//*********************************************************************************************************************
4'b1011:begin /*DO NOT MODIFY--I FORMAT STARTS HERE--LOAD*/
alu_op<=4'b0;
reg_wrt<=1'b1;
re<=1'b1;
wr<=1'b0;
Mux1<=1'b0;
Mux2<=2'b01;
Mux3<=1'b1;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end
//********************************************************************************************************************
4'b1100:begin /*DO NOT MODIFY--I FORMAT--STORE*/
alu_op<=4'b0;
reg_wrt<=1'b0;
re<=1'b0;
wr<=1'b1;
Mux1<=1'b1;
Mux2<=2'b01;
Mux3<=1'b1;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end   /* DO NOT MODIFY--I FORMAT ENDS HERE  */
//********************************************************************************************************************
4'b1101:begin /* DO NOT MODIFY -- BEQ  */
alu_op<=4'b0001;
reg_wrt<=1'b0;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b0;
Mux3<=1'b0;
Mux5<=1'b1;
MuxAlu<=1'b0;
branch<=1'b1;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end   /* DO NOT MODIFY -- BEQ */
//*******************************************************************************************************************
4'b1110:begin /* DO NOT MODIFY -- JMP  */
alu_op<=4'b1110;
reg_wrt<=1'b0;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=2'b10;
Mux3<=1'b0;
Mux5<=1'b0;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b1;
pstate<=s0;
end   
endcase
end
s2:begin
reg_wrt<=1'b0;
re<=1'b0;
wr<=1'b0;
Mux1<=1'b0;
Mux2<=1'b0;
Mux3<=1'b0;
alu_op<=4'bxxxx;
MuxAlu<=1'b0;
branch<=1'b1;
pc_sel<=1'b0;
im_select<=1'b0;
pstate<=s0;
end
s3:begin
reg_wrt<=1'b1;
re<=1'bx;
wr<=1'b0;
Mux1<=1'b1;
Mux2<=1'b1;
Mux3<=1'b1;
alu_op<=4'bxxxx;
MuxAlu<=1'b0;
branch<=1'b0;
pc_sel<=1'b0;
im_select<=1'b0;
pstate<=s0;
end
endcase
end
endmodule

Risc Top Module
**************************************************************************************
module risc(clk,reset);
input clk,reset;
wire [3:0]opcode;
wire [3:0]alu_op;
wire [2:0] alu_sel;
wire [1:0] opb_sel,data_sel;
wire [15:0] outA;
wire carry,reset,reg_wrt,re,wr,Mux1,Mux2,Mux3,branch,im_wrt,sel1,sel2,sel3;
control control_path(alu_op,opcode,clk,carry,reset,reg_wrt,re,wr,sel1,sel2,sel3,sel5,sel6,branch,pc_sel,im_select);
datapath data_path(alu_op,opcode,clk,carry,sel1,sel2,sel3,sel5,sel6,re,wr,reg_wrt,reset,pc_sel,im_select,branch);

endmodule

Testbench
**************************************************************************************

`timescale 1ns / 1ps



////////////////////////////////////////////////////////////////////////////////

// Company: 

// Engineer:

//

// Create Date:   02:38:30 04/03/2017

// Design Name:   risc

// Module Name:   F:/Season 1/RiscPipeline/JIZ.v

// Project Name:  RiscPipeline
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: risc
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module JIZ;

// Inputs
reg clk;
reg reset;

// Instantiate the Unit Under Test (UUT)
risc uut (
.clk(clk), 
.reset(reset)
);

initial begin
// Initialize Inputs
clk = 0;
reset = 0;

// Wait 100 ns for global reset to finish
#40$finish;
        
// Add stimulus here

end
always #1 clk = !clk;
      
endmodule

**************************************************************************************
For more details amigos you can also visit my page

Here is the Data Path of processor

However if you cannot find image in fine condition you can mail me at 
shashisuman17@aol.com. I will send highest quality Datapath

The schematic block diagram


Here is the processor in action


ISA as per my design- Can be modified too
15 GPRs in Register File
R0 always contains zero. Modify it as you want but not recommended.
Instructions are represented by 2 bytes.
LOAD and STORE moves data to and forth from register to RAM and vice versa

Cheers Guys- If you get in some trouble comment and if you have found some mistakes be kind to inform me. :)


Patch 1.0.0 released - Download
1. JIZ instruction has been added.
    Opcode 1111 if Register has content as zero then it will jump to the given address

If you face any problem with code reply immediately
So Long :)

18 comments:

  1. Can you share the ISA for above architecture?
    Are you following MIPS?

    ReplyDelete
    Replies
    1. Yes I am
      But I have excluded shift left 2 because it is required when we jump by 4 to next pc_address to remove last 2 zeros. But here we don't need it. I have modified and verified it.

      Delete
  2. I used it and got A grade from my teacher however I am a bit confused. Why have you avoided alucontrol instead used opcode directly from control unit ?
    Are you goin to add more instructions ?
    :)

    ReplyDelete
    Replies
    1. Congo !!
      Well alucontrol was somehow taking a clock cycle and was making my processor a delay with 1 CC.
      Yes there are 2 more patches coming soon. :)

      Delete
  3. hi,shashi suman
    I use your all code to simulation,but it can't run wave , a lot of signal
    display "Z" (Hign resistance) , Have your code wrong ? or imcomplete ?

    ReplyDelete
  4. hi,shashi suman,I use your all code to simulation , but it can't run wave,
    a lot of signal display "Z"(high resistance) , have your code wrong? or incomplete ?

    ReplyDelete
  5. Hello Tony, the code is complete,
    You must simulate the top level module, This will only show the wave of clk and reset, however other waves can be added using the navigation to all modules from the navigator at left side in Xilinx Simulator.

    ReplyDelete
  6. hi , I have a question , your sel2 only 1 bit ,but sel2 control mux have 3 state (00 01 10) ?

    ReplyDelete
    Replies
    1. Correct Bro ! I have changed it. Thanks for reviewing.
      The sel 10 state gets used only in JMP format so it was a relief.
      Also ran prime and Fibonacci on this code.

      Delete
  7. Your code is poorly documented!!!!
    Try to make it readable next time.

    ReplyDelete
  8. which module remain at top level ?
    and provide sequence of module and how to connect all module in quartus II software

    ReplyDelete
    Replies
    1. The risc module is the top module with only clock and reset pins. Sorry for late reply

      Delete
    2. okay no problem , after successful compilation clock and reset pins are there then how to check final output ? and what kind of output should be there?

      Delete
    3. If you are using Xilinx then in the simulation windows check the left pane
      It will show all modules.
      All you have to do is add any port of the module to the wave window by dragging or right click and add.

      Delete
    4. Regarding What kind of output should be there?
      Well you have to provide the right instruction and the program will do operation according to the opcode and it will be stored in the destination register whih you will have to drag in the window to see the stored value

      Delete
    5. i am using quartus II software any idea about that?

      Delete