-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCP0.v
109 lines (95 loc) · 2.45 KB
/
CP0.v
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
module CP0(
input clk,
input rst,
input mfc0,//读cp0寄存器
input mtc0,//写cp0寄存器
input [31:0]pc,
input [4:0]Rd,//写cp0寄存器地址
input [31:0]wdata,//写cp0寄存器值
input exception,
input eret,//eret异常返回
input [4:0]cause,//中断序号,5'b01000(syscall) 5'b01001(break) 5'b01101(teq)
input intr,//外部中断,没用
output [31:0]rdata,//读到的cp0寄存器值
output [31:0]status,
output reg timer_int,//定时产生外部中断,没用
output reg [31:0]exc_addr
);
reg [31:0] reg_cp0[0:31];
/*status:12号寄存器,cause:13号寄存器,epc:14号寄存器*/
/*cause[6:2]为异常类型号,5'b01000(syscall) 5'b01001(break) 5'b01101(teq)*/
assign rdata = mfc0 ? reg_cp0[Rd] : 0;
assign status = reg_cp0[12];
always @(posedge clk or posedge rst)
begin
if(rst==1'b1)
begin
reg_cp0[12]=32'h0000000f;
reg_cp0[13]=32'h00000000;
reg_cp0[14]=32'h00000000;
exc_addr=32'h00400000;
end
else if(mtc0==1'b1)
begin
reg_cp0[Rd]=wdata;
exc_addr=32'h00400004;//异常地址入口为0x4
end
else if(exception==1'b1)
begin
if(eret==1'b1)
begin
reg_cp0[12]=reg_cp0[12]>>5;//关闭异常,右移5位,开中断
exc_addr=reg_cp0[14];
end
else if(cause==5'b01000)//syscall
begin
if(reg_cp0[12][1]==1'b1)
begin
exc_addr=32'h00400004;//异常地址入口为0x4
reg_cp0[12]=(reg_cp0[12]<<5);
reg_cp0[13][6:2]=5'b01000;
reg_cp0[14]=pc;
end
else
begin
exc_addr=pc+4;
end
end
else if(cause==5'b01001)//break
begin
if(reg_cp0[12][2]==1'b1)
begin
exc_addr=32'h00400004;//异常地址入口为0x4
reg_cp0[12]=reg_cp0[12]<<5;
reg_cp0[13][6:2]=5'b01001;
reg_cp0[14]=pc;
end
else
begin
exc_addr=pc+4;
end
end
else if(cause==5'b01101)//teq
begin
if(reg_cp0[12][3]==1'b1)
begin
exc_addr=32'h00400004;//异常地址入口为0x4
reg_cp0[12]=reg_cp0[12]<<5;
reg_cp0[13][6:2]=5'b01101;
reg_cp0[14]=pc;
end
else
begin
exc_addr=pc+4;
end
end
else
begin
//其他指令,未实现
end
end
else
begin
end
end
endmodule