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
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 endmoduleProgram ROM , from where PC will get Instruction Register to execute commandsmodule 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 processorRISC wrapper connecting everythingmodule 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
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
No comments:
Post a Comment