summaryrefslogtreecommitdiff
path: root/datapath/v0.1/data_path.v
blob: aee5739d7d971cb40a8bf6db0290c852b7d66980 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
module data_path(
    input clk,
    input jump,mem_read, mem_write, alu_src, reg_dst, mem_to_reg, reg_write, bne, beq,
    input [1:0]alu_op,
    output [3:0]opcode    
);

reg [15:0]pc_current;
wire [15:0]pc_next;
wire [15:0]pc_2;
wire [15:0]instr;
wire [2:0]reg_write_dest;
wire [15:0]reg_write_data;
wire [2:0]reg_read_addr_1;
wire [15:0]reg_read_data_1;
wire [2:0]reg_read_addr_2;
wire [15:0]reg_read_data_2;
wire [15:0]ext_im;
wire [15:0]read_data2;
wire [2:0]alu_control;
wire [15:0]alu_out;
wire zero_flag;
wire [15:0]pc_j;
wire [15:0]pc_beq;
wire [15:0]pc_beq2;
wire [15:0]pc_bne;
wire [15:0]pc_bne2;
wire beq_control;
wire bne_control;
wire [12:0]jump_shift;
wire [15:0]mem_read_data;

//set start position counter to 0
initial begin 
    pc_current <= 16'd0;
end

//on pos edge set poisition counter to next value
always @(posedge clk) 
begin
    pc_current <= pc_next;
end

//set value of next instruction position
assign pc_2 = pc_current + 16'd2;

//read current instruction from pc_current and write to instr
instr_memory im(
    .pc(pc_current), 
    .instruction(instr)
);

//jump shift 2
assign jump_shift = {instr[11:0],1'b0};

//register where to write data
assign reg_write_dest = (reg_dst==1'b1) ? instr[5:3] : instr[8:6];

//2 read register addresses
assign reg_read_addr_1 = instr[11:9];
assign reg_read_addr_2 = instr[8:6];


//General purpose register,process values according to settings
gpr_register gpr(
    .clk(clk),
    .reg_write_en(reg_write),
    .reg_write_dest(reg_write_dest),
    .reg_write_data(reg_write_data),
    .reg_read_addr_1(reg_read_addr_1),
    .reg_read_data_1(reg_read_data_1),
    .reg_read_addr_2(reg_read_addr_2),
    .reg_read_data_2(reg_read_data_2)
);

//imidiate extend, set all higher bits to value of the last bit
assign ext_im = {{10{instr[5]}}, instr[5:0]};

//alu control unit
alu_control ac(
    .alu_op(alu_op),
    .opcode(instr[15:12]),
    .alu_cnt(alu_control)
);

// multiplexer read from ext or from data register
//read imidiate value or one from alu
assign read_data2 = (alu_src==1'b1) ? ext_im : reg_read_data_2;

alu alu(
    .a(reg_read_data_1),
    .b(read_data2),
    .alu_sel(alu_control),
    .alu_out(alu_out),
    .carry_out(zero_flag)
);

//position counter values if 
assign pc_beq = pc_2 + {ext_im[14:0], 1'b0};
assign pc_bne = pc_2 + {ext_im[14:0], 1'b0};

assign beq_control = beq & zero_flag;
assign bne_control = bne & (~zero_flag);

//if beq then jump imidiate value, else jump +2 positions
assign pc_beq2 = (beq_control == 1'b1) ? pc_beq : pc_2; 
//if bne jusm imidiate value, else jump beq value
assign pc_bne2 = (bne_control == 1'b1) ? pc_bne : pc_beq2;

assign pc_j = {pc_2[15:13],jump_shift};

assign pc_next = (jump == 1'b1) ? pc_j : pc_bne2;

data_memory dm(
    .clk(clk),
    .mem_access_addr(alu_out),
    .mem_write_data(reg_read_data_2),
    .mem_write_en(mem_write),
    .mem_read(mem_read),
    .mem_read_data(mem_read_data)
);

//writeback
assign reg_write_data = (mem_to_reg == 1'b1)? mem_read_data : alu_out;

assign opcode = instr[15:12];


endmodule