1 |
2 |
ultro |
module sub86( CLK, RSTN, IA, ID, A, D, Q, WEN,BEN );
|
2 |
3 |
ultro |
input CLK,RSTN;
|
3 |
2 |
ultro |
output [31:0] IA;
|
4 |
|
|
input [15:0] ID;
|
5 |
|
|
output [31:0] A;
|
6 |
|
|
input [31:0] D;
|
7 |
|
|
output [31:0] Q;
|
8 |
|
|
output WEN;
|
9 |
|
|
output [1:0] BEN;
|
10 |
|
|
wire nncry,neqF,ngF,nlF;
|
11 |
|
|
reg [31:0] EAX,EBX,ECX,EDX,EBP,ESP,PC,regsrc,regdest,alu_out;
|
12 |
|
|
reg [4:0] state,nstate;
|
13 |
3 |
ultro |
wire [4:0] shtr;
|
14 |
2 |
ultro |
reg [2:0] src,dest;
|
15 |
3 |
ultro |
reg cry,ncry,prefx,nprefx,cmpr,eqF,gF,lF;
|
16 |
2 |
ultro |
wire [31:0] incPC,Sregsrc,Zregsrc,pc_jg,pc_jge,pc_jl,pc_jle,pc_eq,pc_jp,pc_neq;
|
17 |
|
|
wire signed [31:0] sft_in,sft_out,tst;
|
18 |
3 |
ultro |
wire [32:0] adder_out,sub_out;
|
19 |
2 |
ultro |
`define fetch 5'b00000
|
20 |
|
|
`define jmp 5'b00001
|
21 |
|
|
`define jmp2 5'b00010
|
22 |
|
|
`define jge 5'b00011
|
23 |
|
|
`define jge2 5'b00100
|
24 |
|
|
`define imm 5'b00101
|
25 |
|
|
`define imm2 5'b00110
|
26 |
|
|
`define lea 5'b00111
|
27 |
|
|
`define lea2 5'b01000
|
28 |
|
|
`define call 5'b01001
|
29 |
|
|
`define call2 5'b01010
|
30 |
|
|
`define ret 5'b01011
|
31 |
|
|
`define ret2 5'b01100
|
32 |
|
|
`define shift 5'b01110
|
33 |
|
|
`define jg 5'b01111
|
34 |
|
|
`define jg2 5'b10000
|
35 |
|
|
`define jl 5'b10001
|
36 |
|
|
`define jl2 5'b10010
|
37 |
|
|
`define jle 5'b10011
|
38 |
|
|
`define jle2 5'b10100
|
39 |
|
|
`define je 5'b10101
|
40 |
|
|
`define je2 5'b10110
|
41 |
|
|
`define jne 5'b10111
|
42 |
|
|
`define jne2 5'b11000
|
43 |
3 |
ultro |
`define mul 5'b11001
|
44 |
|
|
`define mul2 5'b11010
|
45 |
2 |
ultro |
always @(posedge CLK or negedge RSTN)
|
46 |
|
|
if(!RSTN) begin
|
47 |
3 |
ultro |
EAX <= 32'b0; EBX <= 32'b0; ECX <= 32'b0; EDX <= 32'b0;
|
48 |
|
|
EBP <= 32'b0; ESP <= 32'b011111111; PC <= 32'b00000;
|
49 |
2 |
ultro |
eqF <= 1'b0; lF <= 1'b0; gF <= 1'b0;
|
50 |
3 |
ultro |
state <=5'b00000; prefx <= 1'b0; cry <= 1'b0;
|
51 |
2 |
ultro |
end
|
52 |
|
|
else
|
53 |
|
|
begin
|
54 |
|
|
state <= nstate; prefx <= nprefx; cry <= ncry;
|
55 |
|
|
case (cmpr)
|
56 |
|
|
1'b1 : begin eqF <= neqF ; lF <= nlF; gF <= ngF; end
|
57 |
|
|
default: begin eqF <= eqF ; lF <= lF; gF <= gF; end
|
58 |
|
|
endcase
|
59 |
|
|
if ((state==`fetch) || (state==`ret))
|
60 |
|
|
begin
|
61 |
|
|
if (dest==3'b000) EAX <= alu_out; else EAX<=EAX;
|
62 |
|
|
if (dest==3'b001) ECX <= alu_out; else ECX<=ECX;
|
63 |
|
|
if (dest==3'b010) EDX <= alu_out; else EDX<=EDX;
|
64 |
|
|
if (dest==3'b011) EBX <= alu_out; else EBX<=EBX;
|
65 |
|
|
if (dest==3'b100) ESP <= alu_out; else ESP<=ESP;
|
66 |
|
|
if (dest==3'b101) EBP <= alu_out; else EBP<=EBP;
|
67 |
|
|
end
|
68 |
3 |
ultro |
else if (state==`mul)
|
69 |
|
|
begin
|
70 |
|
|
EAX <= {EAX[30:0],1'b0};
|
71 |
|
|
if (EDX[0] == 1'b1) EBX <= EBX + EAX; else EBX <= EBX;
|
72 |
|
|
EDX <= {1'b0,EDX[31:1]};
|
73 |
|
|
ECX <= ECX; ESP <= ESP; EBP <= EBP;
|
74 |
|
|
end
|
75 |
|
|
else if (state==`mul2)
|
76 |
|
|
begin
|
77 |
|
|
EAX <= EBX; EBX <= EBX; EDX <= EDX;
|
78 |
|
|
ECX <= ECX; ESP <= ESP; EBP <= EBP;
|
79 |
|
|
end
|
80 |
2 |
ultro |
else
|
81 |
3 |
ultro |
begin
|
82 |
|
|
EBP<=EBP; EAX<=EAX;ECX<=ECX; EDX<=EDX;
|
83 |
2 |
ultro |
case(state)
|
84 |
|
|
`jmp , `jg, `jge , `jl, `jle, `je, `jne, `imm, `call,
|
85 |
|
|
`lea : EBX<={EBX[31:16],ID[7:0],ID[15:8]};
|
86 |
|
|
`imm2 : EBX<={ID[7:0],ID[15:8], EBX[15:0]};
|
87 |
|
|
`lea2 : EBX<={ID[7:0],ID[15:8], EBX[15:0]}+EBP;
|
88 |
|
|
default : EBX<=EBX;
|
89 |
|
|
endcase
|
90 |
|
|
case(state)
|
91 |
|
|
`call : ESP<=ESP - 4'b0100;
|
92 |
|
|
`ret2 : ESP<=ESP + 4'b0100;
|
93 |
|
|
default: ESP<=ESP;
|
94 |
|
|
endcase
|
95 |
|
|
end
|
96 |
|
|
case(state)
|
97 |
|
|
`jge2 : PC<=pc_jge;
|
98 |
|
|
`jle2 : PC<=pc_jle;
|
99 |
|
|
`jg2 : PC<=pc_jg ;
|
100 |
|
|
`jl2 : PC<=pc_jl ;
|
101 |
|
|
`je2 : PC<=pc_eq ;
|
102 |
|
|
`jne2 : PC<=pc_neq;
|
103 |
|
|
`jmp2,`call2 : PC<=pc_jp ;
|
104 |
|
|
`ret2 : PC<=D ;
|
105 |
3 |
ultro |
`mul,`mul2 : PC<=PC ;
|
106 |
2 |
ultro |
default : PC<=incPC ;
|
107 |
|
|
endcase
|
108 |
|
|
end
|
109 |
|
|
// muxing for source selection, used in alu & moves
|
110 |
|
|
always@(src,EAX,ECX,EDX,EBX,ESP,EBP,D)
|
111 |
|
|
case(src)
|
112 |
|
|
3'b000 : regsrc = EAX;
|
113 |
|
|
3'b001 : regsrc = ECX;
|
114 |
|
|
3'b010 : regsrc = EDX;
|
115 |
|
|
3'b011 : regsrc = EBX;
|
116 |
|
|
3'b100 : regsrc = ESP;
|
117 |
|
|
3'b101 : regsrc = EBP;
|
118 |
|
|
3'b111 : regsrc = D;
|
119 |
|
|
default: regsrc = EBX;
|
120 |
|
|
endcase
|
121 |
|
|
// muxing for 2nd operand selection, used in alu only
|
122 |
|
|
always@(dest,EAX,ECX,EDX,EBX,ESP,EBP,D)
|
123 |
|
|
case(dest)
|
124 |
|
|
3'b000 : regdest = EAX;
|
125 |
|
|
3'b001 : regdest = ECX;
|
126 |
|
|
3'b010 : regdest = EDX;
|
127 |
|
|
3'b011 : regdest = EBX;
|
128 |
|
|
3'b100 : regdest = ESP;
|
129 |
|
|
3'b101 : regdest = EBP;
|
130 |
|
|
3'b111 : regdest = D ;
|
131 |
|
|
default: regdest = EBX;
|
132 |
|
|
endcase
|
133 |
|
|
// alu
|
134 |
3 |
ultro |
always@(regdest,regsrc,ID,cry,Zregsrc,Sregsrc,sft_out,adder_out,sub_out)
|
135 |
2 |
ultro |
begin
|
136 |
|
|
case (ID[15:10])
|
137 |
|
|
6'b000000 : {ncry,alu_out} = adder_out ; // ADD , carry generation
|
138 |
|
|
6'b000010 : {ncry,alu_out} = {cry,regdest | regsrc}; // OR
|
139 |
|
|
6'b000100 : {ncry,alu_out} = adder_out ; // ADD , carry use
|
140 |
|
|
6'b000110 : {ncry,alu_out} = sub_out ; // SUB , carry use
|
141 |
|
|
6'b001000 : {ncry,alu_out} = {cry,regdest & regsrc}; // AND
|
142 |
|
|
6'b001010 : {ncry,alu_out} = sub_out ; // SUB , carry generation
|
143 |
|
|
6'b001100 : {ncry,alu_out} = {cry,regdest ^ regsrc}; // XOR
|
144 |
|
|
6'b100010 : {ncry,alu_out} = {cry, regsrc}; // MOVE
|
145 |
|
|
6'b101101 : {ncry,alu_out} = {cry, Zregsrc}; // MOVE
|
146 |
|
|
6'b101111 : {ncry,alu_out} = {cry, Sregsrc}; // MOVE
|
147 |
|
|
6'b110000 : {ncry,alu_out} = {cry, sft_out[31:0]}; // SHIFT
|
148 |
|
|
6'b110100 : {ncry,alu_out} = {cry, sft_out[31:0]}; // SHIFT
|
149 |
|
|
default : {ncry,alu_out} = {cry,regdest }; // DO NOTHING
|
150 |
|
|
endcase
|
151 |
|
|
end
|
152 |
|
|
// Main instruction decode
|
153 |
3 |
ultro |
always @(ID,state,EDX)
|
154 |
2 |
ultro |
begin
|
155 |
|
|
// One cycle instructions, operand selection
|
156 |
|
|
if (state == `fetch)
|
157 |
|
|
begin
|
158 |
|
|
case ({ID[15:14],ID[9],ID[7]})
|
159 |
|
|
4'b1000 : begin src=ID[5:3]; dest= 3'b111; end // store into ram (x89 x00)
|
160 |
|
|
4'b1010 : begin src= 3'b111; dest=ID[5:3]; end // load from ram (x8b x00)
|
161 |
|
|
4'b1001 : begin src=ID[5:3]; dest=ID[2:0]; end // reg2reg xfer (x89 xC0)
|
162 |
3 |
ultro |
4'b1011 : begin src=ID[2:0]; dest=ID[5:3]; end // reg2reg xfer (x8b xC0)
|
163 |
2 |
ultro |
4'b0001 : begin src=ID[5:3]; dest=ID[2:0]; end // alu op
|
164 |
|
|
4'b0011 : begin src=ID[2:0]; dest=ID[5:3]; end // alu op
|
165 |
|
|
default : begin src=ID[5:3]; dest=ID[2:0]; end // shift
|
166 |
|
|
endcase
|
167 |
|
|
end
|
168 |
|
|
else if (state==`ret)
|
169 |
|
|
begin src = 3'b011; dest = 3'b100; end
|
170 |
|
|
else begin src = 3'b000; dest = 3'b000; end
|
171 |
|
|
// instructions that require more than one cycle to execute
|
172 |
|
|
if (state == `fetch)
|
173 |
|
|
begin
|
174 |
|
|
casex(ID)
|
175 |
|
|
16'h90e9: nstate = `jmp;
|
176 |
|
|
16'h0f8f: nstate = `jg;
|
177 |
|
|
16'h0f8e: nstate = `jle;
|
178 |
|
|
16'h0f8d: nstate = `jge;
|
179 |
|
|
16'h0f8c: nstate = `jl;
|
180 |
|
|
16'h0f85: nstate = `jne;
|
181 |
|
|
16'h0f84: nstate = `je;
|
182 |
|
|
16'h90bb: nstate = `imm;
|
183 |
|
|
16'h8d9d: nstate = `lea;
|
184 |
|
|
16'h90e8: nstate = `call;
|
185 |
|
|
16'h90c3: nstate = `ret;
|
186 |
3 |
ultro |
16'hc1xx: nstate = `shift;
|
187 |
|
|
16'hafc2: nstate = `mul;
|
188 |
2 |
ultro |
default : nstate = `fetch;
|
189 |
|
|
endcase
|
190 |
|
|
if (ID == 16'h9066) nprefx = 1'b1; else nprefx = 1'b0;
|
191 |
|
|
if (ID[15:8] == 8'h39 ) cmpr = 1'b1; else cmpr = 1'b0;
|
192 |
|
|
end
|
193 |
|
|
else
|
194 |
|
|
begin
|
195 |
3 |
ultro |
nprefx = 1'b0; cmpr = 1'b0;
|
196 |
|
|
if((state==`mul)&&!(EDX==32'b0)) nstate=`mul;
|
197 |
|
|
else if((state==`mul)&& (EDX==32'b0)) nstate=`mul2;
|
198 |
|
|
else if (state==`mul2) nstate = `fetch;
|
199 |
|
|
else if (state==`jmp) nstate = `jmp2; else if (state==`jmp2) nstate = `fetch;
|
200 |
2 |
ultro |
else if (state==`jne) nstate = `jne2; else if (state==`jne2) nstate = `fetch;
|
201 |
|
|
else if (state==`je ) nstate = `je2 ; else if (state==`je2 ) nstate = `fetch;
|
202 |
|
|
else if (state==`jge) nstate = `jge2; else if (state==`jge2) nstate = `fetch;
|
203 |
|
|
else if (state==`jg ) nstate = `jg2 ; else if (state==`jg2 ) nstate = `fetch;
|
204 |
|
|
else if (state==`jle) nstate = `jle2; else if (state==`jle2) nstate = `fetch;
|
205 |
|
|
else if (state==`jl ) nstate = `jl2 ; else if (state==`jl2 ) nstate = `fetch;
|
206 |
|
|
else if (state==`imm) nstate = `imm2; else if (state==`imm2) nstate = `fetch;
|
207 |
|
|
else if (state==`lea) nstate = `lea2; else if (state==`lea2) nstate = `fetch;
|
208 |
|
|
else if (state==`call) nstate = `call2; else if (state==`call2) nstate = `fetch;
|
209 |
|
|
else if (state==`ret) nstate = `ret2; else if (state==`ret2) nstate = `fetch;
|
210 |
|
|
else if (state==`shift) nstate = `fetch;
|
211 |
|
|
else nstate = `fetch;
|
212 |
|
|
end
|
213 |
|
|
end
|
214 |
|
|
assign IA = PC ;
|
215 |
|
|
assign sft_in = regdest ;
|
216 |
3 |
ultro |
assign A = (state == `call2) ? ESP : EBX ;
|
217 |
2 |
ultro |
assign shtr = ID[12] ? ECX[4:0] : EBX[4:0] ;
|
218 |
|
|
assign Q = (state == `call2) ? incPC : regsrc ;
|
219 |
|
|
assign WEN = (ID[15:8]==8'h90) ? 1'b1 :
|
220 |
|
|
(state == `call2) ? 1'b0 :
|
221 |
|
|
(dest == 3'b111) ? 1'b0 :
|
222 |
|
|
1'b1 ;
|
223 |
|
|
assign tst = sft_in >>> (shtr);
|
224 |
|
|
assign sft_out = (src == 3'b111) ? tst : //sar
|
225 |
|
|
(src == 3'b101) ? (sft_in >> shtr ) : //shr
|
226 |
|
|
(sft_in << shtr ) ; //shl
|
227 |
|
|
assign Sregsrc = ID[8] ? { {16{regsrc[15]}} , regsrc[15:0] } :
|
228 |
|
|
{ {24{regsrc[7] }} , regsrc[7:0] } ;
|
229 |
|
|
assign Zregsrc = ID[8] ? { 16'b0 , regsrc[15:0] } :
|
230 |
|
|
{ 24'b0 , regsrc[7:0] } ;
|
231 |
|
|
assign BEN = (state == `call2 ) ? 1'b1 :
|
232 |
|
|
{ prefx , ID[8] } ;
|
233 |
|
|
assign neqF = (regsrc == regdest) ? 1'b1 : 1'b0;
|
234 |
|
|
assign nlF = (regsrc > regdest) ? 1'b1 : 1'b0;
|
235 |
|
|
assign ngF = (regsrc < regdest) ? 1'b1 : 1'b0;
|
236 |
|
|
assign incPC = PC + 3'b010;
|
237 |
|
|
assign pc_jge = ( eqF|gF) ? pc_jp : incPC;
|
238 |
|
|
assign pc_jle = ( eqF|lF) ? pc_jp : incPC;
|
239 |
|
|
assign pc_jg = ( gF ) ? pc_jp : incPC;
|
240 |
|
|
assign pc_jl = ( lF ) ? pc_jp : incPC;
|
241 |
|
|
assign pc_eq = ( eqF ) ? pc_jp : incPC;
|
242 |
|
|
assign pc_neq = ( eqF ) ? incPC : pc_jp;
|
243 |
|
|
assign pc_jp = incPC+{ID,EBX[15:0]};
|
244 |
|
|
assign adder_out= nncry + regsrc + regdest;
|
245 |
|
|
assign sub_out= regdest - regsrc - nncry;
|
246 |
|
|
assign nncry = ID[12] ? cry : 1'b0;
|
247 |
|
|
endmodule
|