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
|