`timescale 1ns / 1ps
module sing_cyc_datapath(input CLOCK);
wire PCsrc, jump;
wire [31:0] pc_next, pc_target, pc_norm, pc_out, pc_jump;
wire [31:0] pc_curr;
wire [31:0] imm_out;
wire [31:0] Instruction;
wire [31:0] rs1_data, rs2_data, wr_data;
wire [1:0] ALUop, immsrc, resultsrc;
wire datawrite, RegWrite, branch, ALUsrc;
wire [31:0] operand2, ALUResult;
wire Zero, ALUControl;
wire [31:0] DM_out;
mux_2_to_1 mux1(pc_norm, pc_next, pc_target, PCsrc);
mux_2_to_1 mux2(pc_out, pc_norm, pc_jump, jump);
PC PC(pc_curr, pc_out, CLOCK);
Adder A1(pc_next, pc_curr, 32'd4);
Adder A2(pc_jump, pc_curr, imm_out);
Adder A3(pc_target, pc_curr, imm_out);
Instr_Mem IM(Instruction, pc_curr);
RegFile RF(rs1_data, rs2_data, CLOCK, wr_data, Instruction[19:15], Instruction[24:20],
Instruction[11:7], RegWrite);
Main_Decoder Dec(Instruction[6:0], RegWrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite,
resultsrc);
Imm_Extender ImEx(imm_out, Instruction[31:0], immsrc);
mux_2_to_1 mux3(operand2, rs2_data, imm_out, ALUsrc);
ALU ALU(ALUResult, Zero, ALUControl, rs1_data, operand2);
and_gate And1(PCsrc, Zero, branch);
ALU_Decoder ALUdec(ALUControl, ALUop);
Data_Mem DM(DM_out, rs2_data, ALUResult, datawrite, CLOCK);
mux_4_to_1 mux4(wr_data, ALUResult, DM_out, pc_next, resultsrc);
endmodule
`timescale 1ns / 1ps
module Instr_Mem(output reg [31:0] Instr_out, input [31:0] Instr_addr);
reg [7:0] Instr_Mem [0:51];
initial
begin
// addi x1, x0, 0x1000
Instr_Mem[0] = 8'b10010011;
Instr_Mem[1] = 8'b00001000;
Instr_Mem[2] = 8'b00010000;
Instr_Mem[3] = 8'b00010001;
// addi x2, x0, 5
Instr_Mem[4] = 8'b10010011;
Instr_Mem[5] = 8'b00000000;
Instr_Mem[6] = 8'b00000000;
Instr_Mem[7] = 8'b00010010;
// addi x3, x0, 0
Instr_Mem[8] = 8'b10010011;
Instr_Mem[9] = 8'b00000000;
Instr_Mem[10] = 8'b00000000;
Instr_Mem[11] = 8'b00011000;
// addi x4, x0, 4
Instr_Mem[12] = 8'b10010011;
Instr_Mem[13] = 8'b00000000;
Instr_Mem[14] = 8'b00000100;
Instr_Mem[15] = 8'b00100000;
// lw x5, 0(x1)
Instr_Mem[16] = 8'b00000011;
Instr_Mem[17] = 8'b00001000;
Instr_Mem[18] = 8'b00000000;
Instr_Mem[19] = 8'b00110001;
// add x3, x3, x5
Instr_Mem[20] = 8'b00110011;
Instr_Mem[21] = 8'b00000001;
Instr_Mem[22] = 8'b00111000;
Instr_Mem[23] = 8'b00010110;
// addi x1, x1, 4
Instr_Mem[24] = 8'b10010011;
Instr_Mem[25] = 8'b00000100;
Instr_Mem[26] = 8'b00000100;
Instr_Mem[27] = 8'b00110001;
// addi x2, x2, -1
Instr_Mem[28] = 8'b10010011;
Instr_Mem[29] = 8'b11111111;
Instr_Mem[30] = 8'b11111111;
Instr_Mem[31] = 8'b00010010;
// beq x2, x0, end
Instr_Mem[32] = 8'b01100011;
Instr_Mem[33] = 8'b00000001;
Instr_Mem[34] = 8'b00000000;
Instr_Mem[35] = 8'b00110010;
// jal x0, loop
Instr_Mem[36] = 8'b11011111;
Instr_Mem[37] = 8'b11111110;
Instr_Mem[38] = 8'b11111111;
Instr_Mem[39] = 8'b11111110;
// addi x6, x0, 0x1004
Instr_Mem[40] = 8'b10010011;
Instr_Mem[41] = 8'b00001000;
Instr_Mem[42] = 8'b00010001;
Instr_Mem[43] = 8'b00110001;
// sw x3, 0(x6)
Instr_Mem[44] = 8'b00100011;
Instr_Mem[45] = 8'b00000000;
Instr_Mem[46] = 8'b00011000;
Instr_Mem[47] = 8'b00110110;
// jal x0, end
Instr_Mem[48] = 8'b11011111;
Instr_Mem[49] = 8'b00000000;
Instr_Mem[50] = 8'b00000000;
Instr_Mem[51] = 8'b00000000;
end
always@(Instr_addr)
begin
Instr_out = {Instr_Mem [Instr_addr + 3], Instr_Mem [Instr_addr + 2], Instr_Mem [Instr_addr +
1], Instr_Mem [Instr_addr]};
end
endmodule
`timescale 1ns / 1ps
module mux_2_to_1(output [31:0] OUT, input [31:0] val_1, input [31:0] val_2, input select);
assign OUT = (select == 1'b0) ? val_1 : val_2;
endmodule
`timescale 1ns / 1ps
module PC(output reg [31:0] PC_curr, input [31:0] PC_new, input CLK);
initial
begin
PC_curr <= 32'h00000000;
end
always@(posedge CLK)
begin
PC_curr <= PC_new;
end
endmodule
`timescale 1ns / 1ps
module Adder(output [31:0] PC_next_target, input [31:0] PC_curr, input [31:0] offset);
assign PC_next_target = PC_curr + offset;
endmodule
`timescale 1ns / 1ps
module RegFile(output wire [31:0] rs1_data, output wire [31:0] rs2_data, input CLK,
input [31:0] rd_data, input [4:0] rs1, input [4:0] rs2, input [4:0] rd, input RegWrite);
integer i;
reg [31:0] Regfile [31:0];
assign rs1_data = Regfile[rs1];
assign rs2_data = Regfile[rs2];
initial
begin
for(i = 0; i <= 31; i = i + 1)
Regfile[i] = 0;
end
always@(posedge CLK)
if(RegWrite)
begin
Regfile[rd] <= rd_data;
end
else
begin
Regfile[rd] <= 32'hxxxxxxxx;
end
endmodule
`timescale 1ns / 1ps
module Main_Decoder(opcode, regwrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite,
resultsrc);
output reg [1:0] ALUop, immsrc, resultsrc;
output reg regwrite, jump, ALUsrc, branch, datawrite;
input [6:0] opcode;
always@(opcode)
begin
case(opcode)
7'b0000011 : {regwrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite, resultsrc} = {1'b1,
1'b0, 2'b00, 2'b00, 1'b1, 1'b0, 1'b0, 2'b01};
7'b0010011 : {regwrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite, resultsrc} = {1'b1,
1'b0, 2'b10, 2'b00, 1'b1, 1'b0, 1'b0, 2'b00};
7'b1100011 : {regwrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite, resultsrc} = {1'b0,
1'b0, 2'b01, 2'b10, 1'b0, 1'b1, 1'b0, 2'bxx};
7'b0110011 : {regwrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite, resultsrc} = {1'b1,
1'b0, 2'b10, 2'bxx, 1'b0, 1'b0, 1'b0, 2'b00};
7'b1101111 : {regwrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite, resultsrc} = {1'b1,
1'b1, 2'bxx, 2'b11, 1'bx, 1'b0, 1'b0, 2'b10};
7'b0100011 : {regwrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite, resultsrc} = {1'b0,
1'b0, 2'b00, 2'b01, 1'b1, 1'b0, 1'b1, 2'bxx};
default : {regwrite, jump, ALUop, immsrc, ALUsrc, branch, datawrite, resultsrc} =
11'bxxxxxxxxxxx;
endcase
end
endmodule
`timescale 1ns / 1ps
module Imm_Extender(output reg [31:0] Imm_out, input [31:0] instruction, input [1:0] ImSrc);
always@(ImSrc or instruction)
begin
case(ImSrc)
2'b00 : Imm_out = {{20{instruction[31]}}, instruction[31:20]}; // I-Type Instr
2'b01 : Imm_out = {{20{instruction[31]}}, instruction[31:25], instruction[11:7]}; // S-Type
Instr
2'b10 : Imm_out = {{20{instruction[31]}}, instruction[7], instruction[30:25],
instruction[11:8], 1'b0}; // B-Type Instr
2'b11 : Imm_out = {{12{instruction[31]}}, instruction[19:12], instruction[20],
instruction[30:21], 1'b0}; // J-Type Instr
default : Imm_out = 32'hxxxxxxxx;
endcase
end
endmodule
`timescale 1ns / 1ps
module ALU(output reg [31:0] ALUResult, output reg Zero, input ALUControl,
input [31:0] rs1_data, input [31:0] Operand2);
always@(ALUControl)
begin
case(ALUControl)
1'b0 : ALUResult = rs1_data + Operand2;
1'b1 : ALUResult = rs1_data - Operand2;
default : ALUResult = 32'bxxxxxxxx;
endcase
end
always@(ALUResult)
begin
if(ALUResult)
begin
Zero <= 1'b0;
end
else
begin
Zero <= 1'b1;
end
end
endmodule
`timescale 1ns / 1ps
module and_gate(output PCsrc, input zero, input branch);
assign PCsrc = zero & branch;
endmodule
module ALU_Decoder (output reg ALU_control, input [1:0] ALU_op);
always@(*)
begin
case(ALU_op)
2'b00 : ALU_control = 1'b0; // lw and sw instr address addition
2'b10 : ALU_control = 1'b0; // R-type addition instr (add)
2'b01 : ALU_control = 1'b1; // B-type sub instr (beq)
default : ALU_control = 1'bx;
endcase
end
endmodule
module Data_Mem (output [31:0] data_out, input [31:0] data_in, input [31:0] address, input
DataWrite, input CLK);
reg [31:0] DataMem [63:0];
integer i;
initial
begin
for(i = 0; i <= 63; i = i + 1)
DataMem[i] = 0;
end
always@(posedge CLK)
begin
if(DataWrite)
begin
{DataMem[address + 3] , DataMem[address + 2] , DataMem[address + 1] ,
DataMem[address]} <= data_in;
end
end
assign data_out = {DataMem[address + 3] , DataMem[address + 2] , DataMem[address + 1] ,
DataMem[address]};
endmodule
`timescale 1ns / 1ps
module mux_4_to_1(output [31:0] OUT, input [31:0] val_1, input [31:0] val_2, input [31:0] val_3,
input [1:0] select);
assign OUT = (select == 2'b00) ? val_1 :
(select == 2'b01) ? val_2 :
(select == 2'b10) ? val_3 : 32'hxxxxxxxx;
endmodule