---
# System prepended metadata

title: Lab 11_CS22B057

---

# Lab 11
Name: SHIVADHARSHAN S
Roll No.: CS22B057

---
## Question 1

**Processor Design:**

Generated schematic in Vivado

![Vivado schematic](https://hackmd.io/_uploads/Ski8pK3G0.jpg)

**Code**

ALU: Same as previous lab


PC:
```verilog=
module program_counter(pc,clk);
output [31:0] pc;
reg [31:0] pc_i;
input clk;
initial begin
    pc_i <= 0;
end
always @(posedge clk ) begin
    pc_i <= pc_i + 1;
    $display("pc=%d",pc_i);
end

assign pc = pc_i;

endmodule
```
Instruction Memory:
```verilog=
module instruction_memory(read_address,out,clk);
input [31:0] read_address;
input clk;
reg [31:0] output_buffer;
reg [31:0] memory [1023:0];
output [31:0] out;

initial begin
    /*
    add x1 x2 x3
    sub x1 x2 x4
    and x4 x1 x5
    sll x6 x1 x2
    slt x9 x0 x1
    sw x6 1(x0)
    lw x15 1(x0)
    or x8 x1 x15
    */
    memory[0] = 32'b00000000001100010000000010110011;
    memory[1] = 32'b01000000010000010000000010110011;
    memory[2] = 32'b00000000010100001000001000110011;
    memory[3] = 32'b00000000001000001001001100110011;
    memory[4] = 32'b00000000000100000010010010110011;
    memory[5] = 32'b00000000011000000010000010100011;
    memory[6] = 32'b00000000000100000010011110000011;
    memory[7] = 32'b00000000111100001110010000110011;

    //smemory[3] = 32'b10000000001100010000000010110011;
end

always @(*) begin
    output_buffer <= memory[read_address];
    $display("instruction_fetched = %b",output_buffer);
end
assign out = output_buffer;
endmodule
```

Data Memory:

```verilog=
module data_memory(rw,location,out,data,clk);
input rw;
input clk;
input [31:0] data;
input [31:0] location;
output [31:0] out;
reg [31:0] output_buffer;
reg [31:0] memory [1023:0];
always @(*) begin
    if (rw==1'b0) begin
        output_buffer = memory[location];
    end    
    else if (rw==1'b1) begin
        memory[location] = data;
    end
end
assign out = output_buffer;
endmodule
```

register file:

```verilog=
module register_file(data,rs1,rs2,rsd,rw,out1,out2,clk);
reg [31:0] reg_file [31:0];
input clk;
input [4:0]rsd;
input [4:0]rs1;
input [4:0]rs2;
input [31:0] data;
input rw;
output [31:0]out1;
output [31:0]out2;
reg [31:0]outbuffer1;
reg [31:0]outbuffer2;

initial begin
    reg_file[0] = 32'b0;
    reg_file[1] = 32'b0;
    reg_file[2] = 32'b1;
    reg_file[3] = 32'b1;
    reg_file[4] = 32'b0;
    reg_file[5] = 32'b0;
    reg_file[6] = 32'b0;
    reg_file[7] = 32'b0;
    reg_file[8] = 32'b0;
    reg_file[9] = 32'b0;
    reg_file[10] = 32'b0;
    reg_file[11] = 32'b0;
    reg_file[12] = 32'b0;
    reg_file[13] = 32'b0;
    reg_file[14] = 32'b0;
    reg_file[15] = 32'b0;
    reg_file[16] = 32'b0;
    reg_file[17] = 32'b0;
    reg_file[18] = 32'b0;
    reg_file[19] = 32'b0;
    reg_file[20] = 32'b0;
    reg_file[21] = 32'b0;
    reg_file[22] = 32'b0;
    reg_file[23] = 32'b0;
    reg_file[24] = 32'b0;
    reg_file[25] = 32'b0;
    reg_file[26] = 32'b0;
    reg_file[27] = 32'b0;
    reg_file[28] = 32'b0;
    reg_file[29] = 32'b0;
    reg_file[30] = 32'b0;
    reg_file[31] = 32'b0;
end

always @(*) begin
    if (rw==1'b1 && rsd!=1'b0) begin
        reg_file[rsd] <= data;
        $display("wrote %d to %d reg",data,rsd);
    end
    outbuffer1 <= reg_file[rs1];
    outbuffer2 <= reg_file[rs2];
    $display("read %d from %d reg",outbuffer1,rs1);
    
end
assign out1 = outbuffer1;
assign out2 = outbuffer2;
endmodule
```

alu control:
```verilog=
module alu_control(instruction,control);
input [31:0] instruction;
output [6:0] control;
// reg control_state;
// always @(instruction) begin
// control_state <= (instruction[6:0] == 7'b0110011) ? (instruction[14:12] == 3'b000) ?(instruction[31:25] == 7'b0000000) ? 7'b0 : 7'b1 : (instruction[14:12] == 3'b100) ? 7'b10 : (instruction[14:12] == 3'b110) ? 7'b11 : (instruction[14:12] == 3'b111) ? 7'b100 :(instruction[14:12] == 3'b001) ? 7'b101 : (instruction[14:12] == 3'b101) ? (instruction[31:25] == 7'b0000000) ? 7'b110 :7'b111: (instruction[14:12] == 3'b010) ? 7'b1000 :7'b1001: 7'b1;
// end
assign control= (instruction[6:0] == 7'b0110011) ? (instruction[14:12] == 3'b000) ?(instruction[31:25] == 7'b0000000) ? 7'b0 : 7'b1 : (instruction[14:12] == 3'b100) ? 7'b10 : (instruction[14:12] == 3'b110) ? 7'b11 : (instruction[14:12] == 3'b111) ? 7'b100 :(instruction[14:12] == 3'b001) ? 7'b101 : (instruction[14:12] == 3'b101) ? (instruction[31:25] == 7'b0000000) ? 7'b110 :7'b111: (instruction[14:12] == 3'b010) ? 7'b1000 :7'b1001: 7'b0;
endmodule
```

control:

```verilog=
module control_path(opcode,mem_read,mem_to_reg,reg_write,mem_write,alu_src,clk);
input [6:0] opcode;
input clk;
output mem_read,mem_to_reg,reg_write,mem_write,alu_src;
reg mem_read_state,mem_to_reg_state,reg_write_state,mem_write_state,alu_src_state;
initial begin
    mem_read_state = 0;
    mem_to_reg_state = 0;
    reg_write_state = 0;
    mem_write_state = 0;
    alu_src_state = 0;
end

// lw 0000011
// sw 0100011
always @(*) begin
    case(opcode)
        7'b0000011: begin  //load
            mem_read_state = 1;
            mem_to_reg_state = 1;
            reg_write_state = 1;
            mem_write_state = 0;
            alu_src_state = 1;
        end
        7'b0100011: begin //store
            mem_read_state = 0;
            mem_to_reg_state = 0;
            reg_write_state = 0;
            mem_write_state = 1;
            alu_src_state = 1;
        end
        7'b0110011: begin // add sub or and etc..
            mem_read_state = 0;
            mem_to_reg_state = 0;
            reg_write_state = 1;
            mem_write_state = 0;
            alu_src_state = 0;
        end
    endcase
end

assign mem_read = mem_read_state;
assign mem_to_reg = mem_to_reg_state;
assign mem_write = mem_write_state;
assign reg_write = reg_write_state;
assign alu_src = alu_src_state;
endmodule
```
datapath: (Top Level)

```verilog=
module datapath(clk);
input clk;
wire [31:0] pc_wire, instruction,write_data,read_data1,read_data2,alu_output,memory_out,alu_2_input,immediate;
wire mem_read,mem_to_reg,reg_write,mem_write,alu_src;
wire [6:0] alu_control_s;
program_counter pc(pc_wire,clk);

instruction_memory instructionMemory(pc_wire,instruction,clk);
data_memory dataMemory(mem_write,alu_output,memory_out,read_data2,clk);

alu_control alucontrol(instruction,alu_control_s);
ALU alu(alu_control_s,read_data1,alu_2_input,alu_output);

assign immediate = (instruction[6:0] == 7'b0000011) ? instruction[31:20] : {instruction[31:25],instruction[11:7]}; 
control_path control(instruction[6:0],mem_read,mem_to_reg,reg_write,mem_write,alu_src,clk);  

assign alu_2_input = alu_src ? immediate : read_data2;
assign write_data = mem_to_reg ? memory_out : alu_output;
register_file reg_file(write_data,instruction[19:15],instruction[24:20],instruction[11:7],reg_write,read_data1,read_data2,clk); 

endmodule
```

TestBench:
```verilog=
module datapath_tb();
reg clk;
datapath dp(clk);

initial begin
    
    #100 clk = 0;
    #100 clk = 1;
    #100 clk = 0;
    #100 clk = 1;
    #100 clk = 0;
    #100 clk = 1;
    #100 clk = 0;
    #100 clk = 1;
    #100 clk = 0;
    #100 clk = 1;
    #100 clk = 0;
    #100 clk = 1;
    #100 clk = 0;
    #100 clk = 1;
    #100 clk = 0;
    #100 clk = 1;
end

endmodule
```

**Output:** (ModelSim)

[Model Sim output pdf](https://drive.google.com/file/d/19BAvPsEH6hRHkWob9lIDgAXndBG10X44/view?usp=sharing)

___

