Hello ,
Sharing my old processor :) CISC processor is coming soon .
Verilog code synthesized/mapped/Place&Routed in Xilinx ISE , Device Vertex 4/XC4VSX25
This in a 16-bit RISC with Hardwired Control UNIT , take 4 cycles for execution .
Capable of Arithmetic/Logic/Branch/Memory instructions with direct and indirect access to RAM locations via general purpose registers 0:15
Memory instructions , address can be stored in one the general purpose registers and can be used to store result at the location
Branch instructions can be unconditional and conditional based on Carry-out flag or Zero-Flag .
Below simulation shows RISC processor running Fibonacci series in
gen_reg[1] = 1 2 3 5 8 13 21 34 55 89 ... (loop) 1 2 3 4 .....
Here goes the code and test-bench for Fibonacci series
ALU Code
module mini_alu (a,b,cin,result,sel,cout);
input [15:0] a,b;
input cin;
output cout;
input [4:0]sel;
output [15:0]result;
reg [15:0] result;
reg cout ;
always @ ( sel or a or b or cin )
begin
case (sel)
5'd0:{cout,result} = a ;
5'd1:{cout,result} = a+1;
5'd2:{cout,result} = a+b;
5'd3:{cout,result} = a+b+cin;
5'd4:{cout,result} = a-1;
5'd5:{cout,result} = a-b;
5'd6:{cout,result} = a-b-cin;
5'd7:{cout,result} = 16'd0;
5'd8:{cout,result} = a|b;
5'd9:{cout,result} = a^b;
5'd10:{cout,result} = a&b;
5'd11:{cout,result} = ~a;
default: {cout,result} = 16'd0;
endcase
end
endmodule
Single Port SRAM with single cycle read and write
module sram(datain,dataout,wr_add,rd_add,clk,enable,read,write);
input clk,enable,read,write;
output [15:0] dataout;
input [15:0]datain;
input [7:0]wr_add,rd_add;
reg [15:0]dataout;
reg [15:0]MEM[255:0];
always @ ( posedge clk )
begin
if (enable == 1'd1 && write == 1'd1)
begin
MEM[wr_add] <= datain ;
end
end
always @ ( posedge clk )
begin
if ( enable == 1'd1 && read == 1'd1 )
begin
dataout <= MEM[rd_add];
end
else
begin
dataout <= dataout;
end
end
endmodule
Program ROM , from where PC will get Instruction Register to execute commands
module program_rom (clk,add,data,enable,rst);
input clk , enable,rst;
input [7:0]add;
output [31:0]data;
wire [31:0]data_wire[255:0];
reg [31:0]data;
// Arithmetic Instructions
assign data_wire[0] = {16'd1,4'd0,4'd0,4'd1,4'b0001};
assign data_wire[1] = {16'd1,4'd0,4'd1,4'd1,4'b0001};
assign data_wire[2] = {16'd2,4'd0,4'd2,4'd1,4'b0001};
assign data_wire[3] = {16'd3,4'd0,4'd3,4'd1,4'b0001};
assign data_wire[4] = {16'd4,4'd0,4'd4,4'd1,4'b0001};
assign data_wire[5] = {16'd5,4'd0,4'd5,4'd1,4'b0001};
assign data_wire[6] = {16'd6,4'd0,4'd6,4'd1,4'b0001};
assign data_wire[7] = {16'd7,4'd0,4'd7,4'd1,4'b0001};
// r8 <- r7
assign data_wire[8] = {16'd7,4'd7,4'd8,4'd1,4'b0001};
//r0 <- r0 + r8
assign data_wire[9] = {16'd0,4'd8,4'd0,4'd2,4'b0001};
// ADI r1 <- r1 + 4
assign data_wire[10] = {16'd4,4'd0,4'd1,4'd8,4'b0001};
// INC r7
assign data_wire[11] = {16'd0,4'd0,4'd7,4'd6,4'b0001};
// DEC r5
assign data_wire[12] = {16'd0,4'd0,4'd5,4'd7,4'b0001};
// SUB r7 <-r7 - r2
assign data_wire[13] = {16'd0,4'd2,4'd7,4'd4,4'b0001};
// SBI r1 4
assign data_wire[14] = {16'd4,4'd0,4'd4,4'd9,4'b0001};
// LOGIC Instruction
// AND r1 r2
assign data_wire[15] = {16'd4,4'd2,4'd1,4'd0,4'b0010};
// ANI r2 , FF
assign data_wire[16] = {16'hFFFF,4'd0,4'd2,4'd1,4'b0010};
// OR r3 , r1
assign data_wire[17] = {16'd0,4'd1,4'd3,4'd2,4'b0010};
//ORI r4,FF
assign data_wire[18] = {16'hFFFF,4'd0,4'd4,4'd3,4'b0010};
// NOT r5
assign data_wire[19] = {16'hFFFF,4'd0,4'd5,4'd4,4'b0010};
// CLEAR r0
assign data_wire[20] = {16'd0,4'd0,4'd0,4'd5,4'b0010};
// Memory Operations
// STI r7 -> @ 01
assign data_wire[21] = {12'd0,8'd1,4'd7,1'd1,1'd0,
1'd0,1'd1,4'b1000};
// ST r7 -> @r0
assign data_wire[22] = {16'd0,4'd0,4'd7,1'd1,1'd0,
1'd1,1'd0,4'b1000};
// LDI r10 <- @01
assign data_wire[23] = {12'd0,8'd1,4'd10,1'd0,1'd1,
1'd0,1'd1,4'b1000} ;
// LDI r11 <- @r0
assign data_wire[24] = {16'd0,4'd0,4'd11,1'd0,1'd1,
1'd0,1'd1,4'b1000} ;
// Load r0 1
assign data_wire[25] = {16'd1,4'd0,4'd1,4'd1,4'b0001};
// Load r1 1
assign data_wire[26] = {16'd1,4'd0,4'd2,4'd1,4'b0001};
assign data_wire[27] = {16'd1,4'd0,4'd3,4'd1,4'b0001};
assign data_wire[28] = {16'd1,4'd0,4'd5,4'd1,4'b0001};
assign data_wire[29] = {16'd5,4'd0,4'd4,4'd1,4'b0001};
// Add r1 <- r1 + r3
assign data_wire[30] = {16'd0,4'd3,4'd1,4'd2,4'b0001};
// Copy r3 <- r2
assign data_wire[31] = {16'd7,4'd2,4'd3,4'd0,4'b0001};
// Copy r2 <- r1
assign data_wire[32] = {16'd7,4'd1,4'd2,4'd0,4'b0001};
// ST r1 -> @r4
assign data_wire[33] = {16'd0,4'd4,4'd1,1'd1,1'd0,1'd1,1'd0,4'b1000};
// INC r4
assign data_wire[34] = {16'd0,4'd0,4'd4,4'd6,4'b0001};
// SUB r1 -
assign data_wire [35] = {16'd89,4'd2,4'd1,4'd10,4'b0001};
assign data_wire[36] = {14'd0,8'd25,4'd3,4'b0100};
assign data_wire[37] = {14'd0,8'd30,4'd0,4'b0100};
assign data_wire[38] = 32'd0;
always @( posedge clk )
begin
if (rst == 1'd1)
begin
data <= 30'd0;
end
else if (enable == 1'd1)
begin
data <= data_wire[add];
end
else
begin
data <= data ;
end
end
endmodule
Here comes Brain of our processor
module controlunit (T0,T4,arith_reg , logic_reg , branch_reg,
alu_op1,alu_op2,regfile_write,
memory_reg,OP1,OP2,sram_write,sram_read,
DI,dec_data,alu_sel,data_bus_sel,
clk,rst,flags
);
input clk ,rst,T0,T4 ;
input [1:0]flags;
output regfile_write;
output [1:0]alu_op1,alu_op2;
output sram_write,sram_read;
output arith_reg , logic_reg , branch_reg, memory_reg ;
output [3:0]OP1,OP2;
output DI ;
output [1:0]data_bus_sel;
output [15:0]dec_data;
output [4:0]alu_sel;
reg [4:0]alu_sel;
reg sram_write,sram_read;
// reg MEM_REG;
reg regfile_write;
reg [3:0]OP1,OP2;
reg DI ;
reg [1:0]data_bus_sel;
reg [15:0]dec_data;
// reg [3:0] old_OP1;
reg [7:0]PC;
wire [31:0]decoded_data;
wire arith_reg , logic_reg , branch_reg, memory_reg ;
wire [3:0]opcode;
reg [1:0]alu_op1,alu_op2;
reg NOP ;
always @ ( * )
begin
if (arith_reg == 1'd1 )
begin
DI = decoded_data[6];
end
else if (memory_reg ==1'd1)
begin
DI = decoded_data[5];
end
else
begin
DI = 1'd1;
end
end
assign arith_reg = decoded_data[0];
assign logic_reg = decoded_data[1];
assign branch_reg = decoded_data[2];
assign memory_reg = decoded_data[3];
always @ ( opcode or branch_reg or flags)
begin
if (branch_reg == 1'd1)
begin
case(opcode)
4'd0:begin
NOP = 1'd1;
end
4'd1:begin
if (flags[1]==1'd1 )
begin
NOP = 1'd1;
end
else
begin
NOP = 1'd0;
end
end
4'd2:begin
if (flags[1]==1'd0)
begin
NOP = 1'd1;
end
else
begin
NOP = 1'd0;
end
end
4'd3:begin
if (flags[0]==1'd1)
begin
NOP = 1'd1;
end
else
begin
NOP = 1'd0;
end
end
4'd4:begin
if (flags[0]==1'd0)
begin
NOP = 1'd1;
end
else
begin
NOP = 1'd0;
end
end
default:begin
NOP = 1'd0;
end
endcase
end
else
begin
NOP = 1'd0;
end
end
always @ ( posedge clk )
begin
if ( rst == 1'd1 )
begin
PC <= 8'd0;
end
else
begin
if (branch_reg == 1'd1 && T4 == 1'd1 )
begin
case(opcode)
4'd0:begin
PC <= decoded_data[31:16];
end
4'd1:begin
if (flags[1]==1'd1 )
begin
PC <= decoded_data[31:16];
end
else
begin
PC <= PC + 1 ;
end
end
4'd2:begin
if (flags[1]==1'd0)
begin
PC <= decoded_data[31:16];
end
else
begin
PC <= PC + 1 ;
end
end
4'd3:begin
if (flags[0]==1'd1)
begin
PC <= decoded_data[15:8];
end
else
begin
PC <= PC + 1 ;
end
end
4'd4:begin
if (flags[0]==1'd0)
begin
PC <= decoded_data[15:8];
end
else
begin
PC <= PC + 1 ;
end
end
default:begin
PC <= PC + 1;
end
endcase
end
else if (T4 == 1'd1)
begin
PC <= PC + 1;
end
else
begin
PC <= PC ;
end
end
end
program_rom u_program_rom(.clk(clk),.add(PC),.rst(rst),
.data(decoded_data),
.enable(T0));
always @ ( * )
begin
if (arith_reg == 1'd1 || logic_reg == 1'd1 )
begin
OP1 =decoded_data[11:8];
end
else if (memory_reg == 1'd1)
begin
OP1 = decoded_data[11:8];
end
else
begin
OP1=4'd0;
end
end
always @ ( * )
begin
if (arith_reg == 1'd1 || logic_reg == 1'd1 )
begin
OP2 = decoded_data[31:16];
end
else if (memory_reg == 1'd1)
begin
OP2 = decoded_data[31:16];
end
else
begin
OP2 = 4'd0;
end
end
always @ ( * )
begin
if (arith_reg == 1'd1 || logic_reg == 1'd1)
begin
dec_data = decoded_data[27:12];
end
else if (memory_reg == 1'd1)
begin
dec_data = decoded_data[31:12];
end
else if (branch_reg == 1'd1)
begin
dec_data = decoded_data[15:0];
end
else
begin
dec_data = 16'd0;
end
end
assign opcode=decoded_data[7:4];
always @ ( * )
begin
if (arith_reg == 1'd1)
begin
case(opcode)
4'd0:
begin
alu_sel = 5'd1;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd0;
regfile_write = 1'd1;
end
4'd1:
begin
alu_sel = 5'd1;
data_bus_sel = 2'd1;
sram_write= 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd0;
regfile_write = 1'd1;
end
4'd2:
begin
alu_sel = 5'd0;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd1;
alu_op1 = 2'd0; alu_op2 = 2'd1;
regfile_write = 1'd0;
end
4'd3:
begin
alu_sel = 5'd3;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd1;
regfile_write = 1'd1;
end
4'd4:
begin
alu_sel = 5'd5;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd2; alu_op2 = 2'd1;
regfile_write = 1'd1;
end
4'd5:
begin
alu_sel = 5'd6;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd1;
regfile_write = 1'd1;
end
4'd6:
begin
alu_sel = 5'd1;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd0;
regfile_write = 1'd1;
end
4'd7:
begin
alu_sel = 5'd4;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd0;
regfile_write = 1'd1;
end
4'd8:
begin
alu_sel = 5'd2;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd2;
regfile_write = 1'd1;
end
4'd9:
begin
alu_sel = 5'd5;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd2;
regfile_write = 1'd1;
end
4'd10:
begin
alu_sel = 5'd5;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd2;
regfile_write = 1'd0;
end
default :
begin
alu_sel = 5'd0;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd0;
regfile_write = 1'd1;
end
endcase
end
else if ( logic_reg == 1'd1 )
begin
case(opcode)
4'd0:
begin
alu_sel = 5'd10;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd1;
regfile_write = 1'd1;
end
4'd1:
begin
alu_sel = 5'd10;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd1;
alu_op1 = 2'd0; alu_op2 = 2'd2;
regfile_write = 1'd0;
end
4'd2:
begin
alu_sel = 5'd8;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd1;
regfile_write = 1'd1;
end
4'd3:
begin
alu_sel = 5'd0;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd2;
regfile_write = 1'd1;
end
4'd4:
begin
alu_sel = 5'd11;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd0;
regfile_write = 1'd1;
end
4'd5:
begin
alu_sel = 5'd7;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd0;
regfile_write = 1'd1;
end
default:
begin
alu_sel = 5'd0;
data_bus_sel = 2'd1;
sram_write = 1'd0; sram_read =1'd0;
alu_op1 = 2'd0; alu_op2 = 2'd0;
regfile_write = 1'd1;
end
endcase
end
else if (memory_reg == 1'd1)
begin
alu_op1 = 2'd1; alu_op2 = 2'd0;
alu_sel = 5'd3;
sram_write = decoded_data[7];
sram_read =decoded_data[6];
if (decoded_data[6]==1'd1)
begin
regfile_write = 1'd1;
data_bus_sel = 2'd0;
end
else if (decoded_data[7]==1'd1)
begin
regfile_write = 1'd0;
data_bus_sel = 2'd1;
end
else
begin
regfile_write = 1'd0;
data_bus_sel = 2'd1;
end
end
else if (branch_reg == 1'd1)
begin
alu_op1 = 2'd1; alu_op2 = 2'd0;
alu_sel = 5'd0;
sram_write = 1'd0; sram_read =1'd0;
regfile_write = 1'd0;
data_bus_sel = 2'd0;
end
else
begin
alu_op1 = 2'd0; alu_op2 = 2'd0;
alu_sel = 5'd0;
sram_write = 1'd0; sram_read =1'd0;
regfile_write = 1'd0;
data_bus_sel = 2'd1;
end
end
endmodule
RISC wrapper connecting everything
module RISC(clk,rst);
input clk,rst;
reg [15:0]gen_reg[15:0];
reg [15:0]databus;
wire [7:0]sram_rd_add;
wire [7:0]sram_wr_add;
wire [1:0]data_bus_sel;
wire [3:0]reg_sel_on_addbus;
wire [7:0]addbus_reg_data;
wire sram_rd , sram_wr;
wire regfile_write,regfile_write_wrap;
wire [15:0] sram_data;
reg [15:0]data_a;
reg [15:0]data_b;
reg cin;
wire [15:0]result;
wire [7:0]mem_add;
wire [15:0]dec_data;
wire [4:0] alu_sel ;
wire DI,sram_write_back_enable;
wire [15:0]data_a_gen_reg,data_b_gen_reg;
wire [3:0]OP1,OP2;
reg [2:0]SC;
wire T0,T1,T2,T3,T4;
wire cout;
reg zero_flag;
wire [1:0]flags;
wire arith_reg , logic_reg , branch_reg, memory_reg ;
wire [1:0]alu_op1,alu_op2;
always @ ( posedge clk )
begin
if ( regfile_write == 1'd1 )
begin
gen_reg[OP1] <= databus;
end
end
controlunit u_controlunit (.T0(T0),.T4(T4),
.regfile_write(regfile_write_wrap),
.alu_op1(alu_op1),.alu_op2(alu_op2),
.sram_write(sram_write_wrap),
.sram_read(sram_read_wrap),
.arith_reg(arith_reg) , .logic_reg(logic_reg) ,
.branch_reg(branch_reg), .memory_reg(memory_reg),
.OP1(OP1),.OP2(OP2),.DI(DI),
.dec_data(dec_data),.alu_sel(alu_sel),
.data_bus_sel(data_bus_sel),
.clk(clk),.rst(rst),.flags(flags)
);
mini_alu u_mini_alu(.a(data_a),.b(data_b),
.cin(cin),.result(result),.cout(cout));
sram u_sram(.datain(databus),.dataout(sram_data),
.wr_add(sram_wr_add),.rd_add(sram_rd_add),.clk(clk),
.enable(sram_write_back_enable),
.read(sram_rd),.write(sram_wr));
// Sram Address controller and Address Bus
assign sram_write_back_enable = memory_reg & ( T2 | T4);
assign sram_rd = memory_reg & sram_read_wrap & T2 ;
assign sram_wr = memory_reg & sram_write_wrap & T4 ;
assign regfile_write = regfile_write_wrap & T4 ;
assign mem_add = dec_data[7:0];
assign reg_sel_on_addbus = OP2;
assign addbus_reg_data = gen_reg[reg_sel_on_addbus];
assign sram_rd_add = DI?addbus_reg_data:mem_add;
assign sram_wr_add = DI?addbus_reg_data:mem_add;
assign data_a_gen_reg = gen_reg[OP1];
assign data_b_gen_reg = gen_reg[OP2];
always @ (result or sram_data or dec_data or data_bus_sel)
begin
case(data_bus_sel)
2'd0:databus = sram_data;
2'd1:databus = result;
2'd2:databus = 16'd0;
2'd3:databus = dec_data;
endcase
end
always @ (alu_op1 or data_a_gen_reg or data_b_gen_reg or dec_data)
begin
case(alu_op1)
2'd0:begin
data_a = data_a_gen_reg;
end
2'd1:begin
data_a = data_b_gen_reg;
end
2'd2:begin
data_a = dec_data;
end
2'd3:begin
data_a = 16'd0;
end
default:begin
data_a = 16'd0;
end
endcase
end
always @ (alu_op2 or data_a_gen_reg or data_b_gen_reg or dec_data )
begin
case(alu_op2)
2'd0:begin
data_b = data_a_gen_reg;
end
2'd1:begin
data_b = data_b_gen_reg;
end
2'd2:begin
data_b = dec_data;
end
2'd3:begin
data_b = 16'd0;
end
default:begin
data_b = 16'd0;
end
endcase
end
always @ (posedge clk)
begin
if ( rst == 1'd1 )
begin
cin <= 1'd0;
end
else
begin
if ( T3 == 1'd1 & (arith_reg == 1'd1 | logic_reg == 1'd1 ))
begin
cin <= cout ;
end
else
begin
cin <= cin ;
end
end
end
assign result_zero = (result == 16'd0);
assign flags = {cin,zero_flag};
always @ ( posedge clk )
begin
if (rst == 1'd0 )
begin
zero_flag <= 1'd0;
end
else
begin
if ( T3 == 1'd1 & (arith_reg == 1'd1 | logic_reg == 1'd1 ))
begin
zero_flag <= result_zero;
end
else
begin
zero_flag <= zero_flag;
end
end
end
assign T0 = (SC == 3'd0);
assign T1 = (SC == 3'd1);
assign T2 = (SC == 3'd2);
assign T3 = (SC == 3'd3);
assign T4 = (SC == 3'd4);
always @ ( posedge clk )
begin
if (rst == 1'd1)
begin
SC <= 3'd0;
end
else
begin
if (T4 == 1'd1)
begin
SC <= 3'd0;
end
else
begin
SC <= SC + 3'd1 ;
end
end
end
endmodule
Test bench for testing our RISC processor
module RISC_test(clk,rst,decoded_data);
output clk,rst;
output [29:0]decoded_data;
reg clk,rst;
reg [29:0]decoded_data;
reg [7:0] temp ;
always
begin
#5 clk = ~ clk ;
end
initial
begin : COUNT
clk = 1'd0;
rst = 1'd1;
// Load r1 with direct data
decoded_data = {7'd0,16'd1,2'd1,4'd1,1'd0};
@ (posedge clk);
#5 rst = 1'd0;
end
RISC u_RISC(clk,rst);
endmodule