1 |
9 |
ns32kum |
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
2 |
|
|
//
|
3 |
|
|
// This file is part of the M32632 project
|
4 |
|
|
// http://opencores.org/project,m32632
|
5 |
|
|
//
|
6 |
|
|
// Filename: I_PFAD.v
|
7 |
13 |
ns32kum |
// Version: 1.1 bug fix
|
8 |
|
|
// History: 1.0 first release of 30 Mai 2015
|
9 |
|
|
// Date: 7 November 2015
|
10 |
9 |
ns32kum |
//
|
11 |
|
|
// Copyright (C) 2015 Udo Moeller
|
12 |
|
|
//
|
13 |
|
|
// This source file may be used and distributed without
|
14 |
|
|
// restriction provided that this copyright statement is not
|
15 |
|
|
// removed from the file and that any derivative work contains
|
16 |
|
|
// the original copyright notice and the associated disclaimer.
|
17 |
|
|
//
|
18 |
|
|
// This source file is free software; you can redistribute it
|
19 |
|
|
// and/or modify it under the terms of the GNU Lesser General
|
20 |
|
|
// Public License as published by the Free Software Foundation;
|
21 |
|
|
// either version 2.1 of the License, or (at your option) any
|
22 |
|
|
// later version.
|
23 |
|
|
//
|
24 |
|
|
// This source is distributed in the hope that it will be
|
25 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
26 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
27 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more
|
28 |
|
|
// details.
|
29 |
|
|
//
|
30 |
|
|
// You should have received a copy of the GNU Lesser General
|
31 |
|
|
// Public License along with this source; if not, download it
|
32 |
|
|
// from http://www.opencores.org/lgpl.shtml
|
33 |
|
|
//
|
34 |
|
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
35 |
|
|
//
|
36 |
|
|
// Modules contained in this file:
|
37 |
|
|
// 1. BITMASK Mask Generator , was a ROM on falling edge in early days
|
38 |
|
|
// 2. MULFILTER Filter for Multiplier Input Data
|
39 |
|
|
// 3. SIGNMUL Signed Multiplier for Integer Multiplication
|
40 |
|
|
// 4. SHIFTER Barrel Shifter for all Shift Opcodes
|
41 |
|
|
// 5. FFS_LOGIK Logic for FFS opcode
|
42 |
|
|
// 6. SCHALE Enclosure for Adder/Subtractor
|
43 |
|
|
// 7. I_PFAD The Integer Datapath
|
44 |
|
|
//
|
45 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
46 |
9 |
ns32kum |
|
47 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
48 |
9 |
ns32kum |
//
|
49 |
|
|
// 1. BITMASK Mask Generator , was a ROM on falling edge in early days
|
50 |
|
|
//
|
51 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
52 |
9 |
ns32kum |
module BITMASK (AA, DOUT);
|
53 |
|
|
|
54 |
|
|
// 0 : FFFFFFFF; Masktype 1 , Zero from right
|
55 |
|
|
// 1 : FFFFFFFE;
|
56 |
|
|
// 2 : FFFFFFFC;
|
57 |
|
|
// 3 : FFFFFFF8;
|
58 |
|
|
// . : ...
|
59 |
|
|
// 32 : 00000001; Masktype 2 , Decoder
|
60 |
|
|
// 33 : 00000002;
|
61 |
|
|
// 34 : 00000004;
|
62 |
|
|
// 35 : 00000008;
|
63 |
|
|
// .. : ...
|
64 |
|
|
// 64 : 00000001; Masktyte 3 , One from right
|
65 |
|
|
// 65 : 00000003;
|
66 |
|
|
// 66 : 00000007;
|
67 |
|
|
// 67 : 0000000F;
|
68 |
|
|
// .. : ...
|
69 |
|
|
// 96 : FFFFFFFF; Masktype 4 , like Masktype 3 but AA-1
|
70 |
|
|
// 97 : 00000001;
|
71 |
|
|
// 98 : 00000003;
|
72 |
|
|
// 99 : 00000007;
|
73 |
|
|
// .. : ...
|
74 |
|
|
|
75 |
|
|
input [6:0] AA;
|
76 |
|
|
|
77 |
|
|
output reg [31:0] DOUT;
|
78 |
|
|
|
79 |
|
|
reg [7:0] dec_bit;
|
80 |
|
|
|
81 |
|
|
wire [4:0] code;
|
82 |
|
|
wire high,low;
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
assign code = AA[4:0] - {4'd0,&AA[6:5]};
|
86 |
|
|
|
87 |
|
|
assign high = (AA[6:5] == 2'd0);
|
88 |
|
|
assign low = AA[6];
|
89 |
|
|
|
90 |
|
|
always @(code or high or low)
|
91 |
|
|
case (code[2:0])
|
92 |
|
|
3'b000 : dec_bit = {{7{high}},1'b1 };
|
93 |
|
|
3'b001 : dec_bit = {{6{high}},1'b1, low };
|
94 |
|
|
3'b010 : dec_bit = {{5{high}},1'b1,{2{low}}};
|
95 |
|
|
3'b011 : dec_bit = {{4{high}},1'b1,{3{low}}};
|
96 |
|
|
3'b100 : dec_bit = {{3{high}},1'b1,{4{low}}};
|
97 |
|
|
3'b101 : dec_bit = {{2{high}},1'b1,{5{low}}};
|
98 |
|
|
3'b110 : dec_bit = { high ,1'b1,{6{low}}};
|
99 |
|
|
3'b111 : dec_bit = { 1'b1,{7{low}}};
|
100 |
|
|
endcase
|
101 |
|
|
|
102 |
|
|
always @(code or high or low or dec_bit)
|
103 |
|
|
case (code[4:3])
|
104 |
|
|
2'b00 : DOUT = {{24{high}},dec_bit };
|
105 |
|
|
2'b01 : DOUT = {{16{high}},dec_bit,{ 8{low}}};
|
106 |
|
|
2'b10 : DOUT = {{ 8{high}},dec_bit,{16{low}}};
|
107 |
|
|
2'b11 : DOUT = { dec_bit,{24{low}}};
|
108 |
|
|
endcase
|
109 |
|
|
|
110 |
|
|
endmodule
|
111 |
|
|
|
112 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
113 |
9 |
ns32kum |
//
|
114 |
|
|
// 2. MULFILTER Filter for Multiplier Input Data
|
115 |
|
|
//
|
116 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
117 |
9 |
ns32kum |
module MULFILTER (BWD, FLOAT, SRC1, SRC2, DEST1, DEST2);
|
118 |
|
|
|
119 |
|
|
input [1:0] BWD;
|
120 |
|
|
input FLOAT;
|
121 |
|
|
input [31:0] SRC1,SRC2;
|
122 |
|
|
output [31:0] DEST1,DEST2;
|
123 |
|
|
|
124 |
|
|
wire sign1,sign2;
|
125 |
|
|
reg [31:0] DEST1,DEST2;
|
126 |
|
|
|
127 |
|
|
assign sign1 = BWD[0] ? SRC1[15] : SRC1[7];
|
128 |
|
|
|
129 |
|
|
always @(FLOAT or BWD or SRC1 or sign1)
|
130 |
|
|
casex ({FLOAT,BWD,sign1})
|
131 |
|
|
4'b0_00_0 : DEST1 = {24'h000000, SRC1[7:0]};
|
132 |
|
|
4'b0_00_1 : DEST1 = {24'hFFFFFF, SRC1[7:0]};
|
133 |
|
|
4'b0_01_0 : DEST1 = { 16'h0000,SRC1[15:0]};
|
134 |
|
|
4'b0_01_1 : DEST1 = { 16'hFFFF,SRC1[15:0]};
|
135 |
|
|
4'b1_xx_x : DEST1 = { 9'h001,SRC1[22:0]};
|
136 |
|
|
default : DEST1 = SRC1;
|
137 |
|
|
endcase
|
138 |
|
|
|
139 |
|
|
assign sign2 = BWD[0] ? SRC2[15] : SRC2[7];
|
140 |
|
|
|
141 |
|
|
always @(FLOAT or BWD or SRC2 or sign2)
|
142 |
|
|
casex ({FLOAT,BWD,sign2})
|
143 |
|
|
4'b0_00_0 : DEST2 = {24'h000000, SRC2[7:0]};
|
144 |
|
|
4'b0_00_1 : DEST2 = {24'hFFFFFF, SRC2[7:0]};
|
145 |
|
|
4'b0_01_0 : DEST2 = { 16'h0000,SRC2[15:0]};
|
146 |
|
|
4'b0_01_1 : DEST2 = { 16'hFFFF,SRC2[15:0]};
|
147 |
|
|
4'b1_xx_x : DEST2 = { 9'h001,SRC2[22:0]};
|
148 |
|
|
default : DEST2 = SRC2;
|
149 |
|
|
endcase
|
150 |
|
|
|
151 |
|
|
endmodule
|
152 |
|
|
|
153 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
154 |
9 |
ns32kum |
//
|
155 |
|
|
// 3. SIGNMUL Signed Multiplier for Integer Multiplication
|
156 |
|
|
//
|
157 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
158 |
9 |
ns32kum |
module SIGNMUL (dataa, datab, result);
|
159 |
|
|
|
160 |
|
|
input signed [31:0] dataa,datab;
|
161 |
|
|
output signed [63:0] result;
|
162 |
|
|
|
163 |
|
|
assign result = dataa * datab;
|
164 |
|
|
|
165 |
|
|
endmodule
|
166 |
|
|
|
167 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
168 |
9 |
ns32kum |
//
|
169 |
|
|
// 4. SHIFTER Barrel Shifter for all Shift Opcodes
|
170 |
|
|
//
|
171 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
172 |
9 |
ns32kum |
module SHIFTER ( MASKE,ROT,LSH,ASH,SIZE,SH_VAL,SH_DAT,SH_OUT,MASK_SEL);
|
173 |
|
|
|
174 |
|
|
input [31:0] MASKE;
|
175 |
|
|
input ROT,LSH,ASH;
|
176 |
|
|
input [1:0] SIZE;
|
177 |
|
|
input [7:0] SH_VAL;
|
178 |
|
|
input [31:0] SH_DAT;
|
179 |
|
|
output [31:0] SH_OUT;
|
180 |
|
|
output [4:0] MASK_SEL;
|
181 |
|
|
|
182 |
|
|
reg [31:0] sh_dat_in;
|
183 |
|
|
wire [31:0] sh_dat_0,sh_dat_1,sh_dat_2,sh_dat_3,sh_dat_4;
|
184 |
|
|
wire [4:0] shift;
|
185 |
|
|
reg msb;
|
186 |
|
|
wire [1:0] mask_code;
|
187 |
|
|
reg [31:0] SH_OUT;
|
188 |
|
|
reg [4:0] MASK_SEL;
|
189 |
|
|
|
190 |
|
|
// Inputstage : prepare for ROT opcode :
|
191 |
|
|
|
192 |
|
|
always @(ROT or SIZE or SH_DAT)
|
193 |
|
|
casex ({ROT,SIZE})
|
194 |
|
|
3'b100 : sh_dat_in = {SH_DAT[31:16],SH_DAT[7:0],SH_DAT[7:0]}; // Byte copy to left
|
195 |
|
|
3'b101 : sh_dat_in = {SH_DAT[15:0],SH_DAT[15:0]}; // Word copy to left
|
196 |
|
|
default : sh_dat_in = SH_DAT;
|
197 |
|
|
endcase
|
198 |
|
|
|
199 |
|
|
// Special case for ROT and BYTE : this way less logic
|
200 |
|
|
|
201 |
|
|
assign shift = (ROT & (SIZE == 2'b00)) ? {2'b11,SH_VAL[2:0]} : SH_VAL[4:0];
|
202 |
|
|
|
203 |
|
|
// Rotation logic
|
204 |
|
|
|
205 |
11 |
ns32kum |
assign sh_dat_0 = shift[0] ? {sh_dat_in[30:0],sh_dat_in[31]} : sh_dat_in; // Rotation of 1 bit position
|
206 |
9 |
ns32kum |
assign sh_dat_1 = shift[1] ? {sh_dat_0[29:0],sh_dat_0[31:30]} : sh_dat_0; // 2
|
207 |
|
|
assign sh_dat_2 = shift[2] ? {sh_dat_1[27:0],sh_dat_1[31:28]} : sh_dat_1; // 4
|
208 |
|
|
assign sh_dat_3 = shift[3] ? {sh_dat_2[23:0],sh_dat_2[31:24]} : sh_dat_2; // 8
|
209 |
|
|
assign sh_dat_4 = shift[4] ? {sh_dat_3[15:0],sh_dat_3[31:16]} : sh_dat_3; // 16
|
210 |
|
|
|
211 |
|
|
// Detection of negativ data
|
212 |
|
|
|
213 |
|
|
always @(SIZE or SH_DAT)
|
214 |
|
|
casex (SIZE)
|
215 |
|
|
2'b00 : msb = SH_DAT[7]; // Byte
|
216 |
|
|
2'b01 : msb = SH_DAT[15]; // Word
|
217 |
|
|
default : msb = SH_DAT[31]; // Double = 11
|
218 |
|
|
endcase
|
219 |
|
|
|
220 |
|
|
// needs mask for output data : SH_VAL[7] says negativ number and "right" shift
|
221 |
|
|
|
222 |
|
|
assign mask_code[1] = ROT | (SH_VAL[7] & ASH & msb);
|
223 |
|
|
assign mask_code[0] = ROT | (SH_VAL[7] & ((ASH & ~msb) | LSH));
|
224 |
|
|
|
225 |
|
|
always @(SH_VAL or SIZE)
|
226 |
|
|
casex ({SH_VAL[7],SIZE})
|
227 |
|
|
3'b100 : MASK_SEL = {2'b00,SH_VAL[2:0]}; // special mask for Byte at right-shift
|
228 |
|
|
3'b101 : MASK_SEL = {1'b0,SH_VAL[3:0]}; // special mask for Word at right-shift
|
229 |
|
|
default : MASK_SEL = SH_VAL[4:0];
|
230 |
|
|
endcase
|
231 |
|
|
|
232 |
|
|
always @(mask_code or sh_dat_4 or MASKE) // top bits of MASKE are "1", lower bits are "0"
|
233 |
|
|
casex (mask_code)
|
234 |
|
|
2'b00 : SH_OUT = sh_dat_4 & MASKE; // LSH and ASH with positiv shift count
|
235 |
|
|
2'b01 : SH_OUT = sh_dat_4 & ~MASKE; // Negativ shift count : LSH or ASH with positiv data
|
236 |
|
|
2'b10 : SH_OUT = sh_dat_4 | MASKE; // ASH with negativ shift count and negativ input data
|
237 |
|
|
default : SH_OUT = sh_dat_4; // ROT
|
238 |
|
|
endcase
|
239 |
|
|
|
240 |
|
|
endmodule
|
241 |
|
|
|
242 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
243 |
9 |
ns32kum |
//
|
244 |
|
|
// 5. FFS_LOGIK Logic for FFS opcode
|
245 |
|
|
//
|
246 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
247 |
9 |
ns32kum |
module FFS_LOGIK (SRC1, SRC2, BWD, FLAG, DOUT);
|
248 |
|
|
|
249 |
|
|
input [31:0] SRC1;
|
250 |
|
|
input [4:0] SRC2;
|
251 |
|
|
input [1:0] BWD;
|
252 |
|
|
output reg FLAG;
|
253 |
|
|
output [4:0] DOUT;
|
254 |
|
|
|
255 |
|
|
reg [6:0] maske;
|
256 |
|
|
reg [7:0] byte_1,byte_2;
|
257 |
|
|
|
258 |
|
|
wire [7:0] byte_0,byte_3;
|
259 |
|
|
wire [15:0] mdat_0;
|
260 |
|
|
wire [7:0] mdat_1;
|
261 |
|
|
wire [3:0] mdat_2;
|
262 |
|
|
wire [1:0] mdat_3;
|
263 |
|
|
wire [4:0] obits;
|
264 |
|
|
|
265 |
|
|
always @(*)
|
266 |
|
|
case (SRC2[2:0])
|
267 |
|
|
3'd0 : maske = 7'h7F;
|
268 |
|
|
3'd1 : maske = 7'h7E;
|
269 |
|
|
3'd2 : maske = 7'h7C;
|
270 |
|
|
3'd3 : maske = 7'h78;
|
271 |
|
|
3'd4 : maske = 7'h70;
|
272 |
|
|
3'd5 : maske = 7'h60;
|
273 |
|
|
3'd6 : maske = 7'h40;
|
274 |
|
|
3'd7 : maske = 7'h00;
|
275 |
|
|
endcase
|
276 |
|
|
|
277 |
|
|
assign byte_0 = (SRC2[4:3] == 2'b00) ? {SRC1[7],(SRC1[6:0] & maske)} : 8'h00;
|
278 |
|
|
|
279 |
|
|
always @(*)
|
280 |
|
|
casex (SRC2[4:3])
|
281 |
|
|
2'b00 : byte_1 = SRC1[15:8];
|
282 |
|
|
2'b01 : byte_1 = {SRC1[15],(SRC1[14:8] & maske)};
|
283 |
|
|
2'b1x : byte_1 = 8'h00;
|
284 |
|
|
endcase
|
285 |
|
|
|
286 |
|
|
always @(*)
|
287 |
|
|
casex (SRC2[4:3])
|
288 |
|
|
2'b0x : byte_2 = SRC1[23:16];
|
289 |
|
|
2'b10 : byte_2 = {SRC1[23],(SRC1[22:16] & maske)};
|
290 |
|
|
2'b11 : byte_2 = 8'h00;
|
291 |
|
|
endcase
|
292 |
|
|
|
293 |
|
|
assign byte_3 = (SRC2[4:3] == 2'b11) ? {SRC1[31],(SRC1[30:24] & maske)} : SRC1[31:24];
|
294 |
|
|
|
295 |
|
|
assign obits[4] = ({byte_1,byte_0} == 16'h0);
|
296 |
|
|
assign mdat_0 = obits[4] ? {byte_3,byte_2} : {byte_1,byte_0}; // 16 Bit
|
297 |
|
|
|
298 |
|
|
assign obits[3] = (mdat_0[7:0] == 8'h0);
|
299 |
|
|
assign mdat_1 = obits[3] ? mdat_0[15:8] : mdat_0[7:0];
|
300 |
|
|
|
301 |
|
|
assign obits[2] = (mdat_1[3:0] == 4'h0);
|
302 |
|
|
assign mdat_2 = obits[2] ? mdat_1[7:4] : mdat_1[3:0];
|
303 |
|
|
|
304 |
|
|
assign obits[1] = (mdat_2[1:0] == 2'b0);
|
305 |
|
|
assign mdat_3 = obits[1] ? mdat_2[3:2] : mdat_2[1:0];
|
306 |
|
|
|
307 |
|
|
assign obits[0] = ~mdat_3[0];
|
308 |
|
|
|
309 |
|
|
always @(BWD or obits or mdat_3)
|
310 |
|
|
casex ({BWD,obits[4:3]})
|
311 |
|
|
4'b00_x1 : FLAG = 1; // Byte Overflow => nothing found
|
312 |
|
|
4'b00_10 : FLAG = 1; // Byte Overflow => nothing found
|
313 |
|
|
4'b01_1x : FLAG = 1; // Word Overflow => nothing found
|
314 |
|
|
default : FLAG = (mdat_3 == 2'b00);
|
315 |
|
|
endcase
|
316 |
|
|
|
317 |
|
|
assign DOUT = FLAG ? 5'h0 : obits;
|
318 |
|
|
|
319 |
|
|
endmodule
|
320 |
|
|
|
321 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
322 |
9 |
ns32kum |
//
|
323 |
|
|
// 6. SCHALE Enclosure for Adder/Subtractor
|
324 |
|
|
//
|
325 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
326 |
9 |
ns32kum |
module SCHALE (dataa, datab, cin, add_sub, bwd, result, cout, overflow);
|
327 |
|
|
|
328 |
|
|
input [31:0] dataa,datab;
|
329 |
|
|
input cin;
|
330 |
|
|
input add_sub; // 1 = Addition , 0 = Subtraction
|
331 |
|
|
input [1:0] bwd;
|
332 |
|
|
|
333 |
|
|
output [31:0] result;
|
334 |
|
|
output cout,overflow;
|
335 |
|
|
|
336 |
|
|
reg [2:0] seldat;
|
337 |
|
|
reg overflow;
|
338 |
|
|
|
339 |
|
|
wire [32:0] summe;
|
340 |
|
|
|
341 |
|
|
assign summe = {1'b0,dataa} + {1'b0,(add_sub ? datab : ~datab)} + {32'd0,cin};
|
342 |
|
|
|
343 |
|
|
always @(bwd or dataa or datab or summe)
|
344 |
|
|
case (bwd)
|
345 |
|
|
2'b00 : seldat = {summe[7], dataa[7], datab[7]};
|
346 |
|
|
2'b01 : seldat = {summe[15],dataa[15],datab[15]};
|
347 |
|
|
default : seldat = {summe[31],dataa[31],datab[31]};
|
348 |
|
|
endcase
|
349 |
|
|
|
350 |
|
|
always @(seldat or add_sub)
|
351 |
|
|
case (seldat[1:0])
|
352 |
|
|
2'b00 : overflow = add_sub ? seldat[2] : 1'b0;
|
353 |
|
|
2'b01 : overflow = add_sub ? 1'b0 : seldat[2];
|
354 |
|
|
2'b10 : overflow = add_sub ? 1'b0 : ~seldat[2];
|
355 |
|
|
2'b11 : overflow = add_sub ? ~seldat[2] : 1'b0;
|
356 |
|
|
endcase
|
357 |
|
|
|
358 |
|
|
assign cout = add_sub ? summe[32] : ~summe[32];
|
359 |
|
|
assign result = summe[31:0];
|
360 |
|
|
|
361 |
|
|
endmodule
|
362 |
|
|
|
363 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
364 |
9 |
ns32kum |
//
|
365 |
|
|
// 7. I_PFAD The Integer Datapath
|
366 |
|
|
//
|
367 |
11 |
ns32kum |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
368 |
|
|
module I_PFAD ( BCLK, BRESET, SFP_DAT, FSR, DP_OUT, SRC1, SRC2, BMASKE, ADDR, MRESULT, OPCODE, BWD, FL, SP_CMP, DP_CMP, LD_OUT,
|
369 |
|
|
WREN, WRADR, RDAA, DETOIP, BITSEL, OVF_BCD, DISP, RWVFLAG, DSR, I_OUT, PSR, BMCODE, OV_FLAG, ACB_ZERO, STRING);
|
370 |
9 |
ns32kum |
|
371 |
|
|
input BCLK,BRESET;
|
372 |
|
|
input [31:0] SFP_DAT,FSR,DP_OUT;
|
373 |
|
|
input [31:0] SRC1,SRC2;
|
374 |
|
|
input [31:0] BMASKE;
|
375 |
|
|
input [31:0] ADDR;
|
376 |
|
|
input [63:0] MRESULT;
|
377 |
|
|
input [7:0] OPCODE;
|
378 |
|
|
input [1:0] BWD;
|
379 |
|
|
input FL;
|
380 |
|
|
input [2:0] SP_CMP;
|
381 |
|
|
input [2:0] DP_CMP;
|
382 |
|
|
input LD_OUT;
|
383 |
|
|
input WREN;
|
384 |
|
|
input [5:0] WRADR;
|
385 |
|
|
input [7:0] RDAA;
|
386 |
|
|
input [11:0] DETOIP;
|
387 |
|
|
input [2:0] BITSEL;
|
388 |
|
|
input [3:0] OVF_BCD;
|
389 |
|
|
input [4:0] DISP;
|
390 |
|
|
input RWVFLAG;
|
391 |
|
|
input [3:0] DSR;
|
392 |
|
|
|
393 |
|
|
output [31:0] I_OUT;
|
394 |
|
|
output [11:0] PSR;
|
395 |
|
|
output [6:0] BMCODE; // ROM Address for BITMASK
|
396 |
|
|
output reg OV_FLAG;
|
397 |
|
|
output ACB_ZERO;
|
398 |
|
|
output [4:0] STRING;
|
399 |
|
|
|
400 |
|
|
reg [31:0] I_OUT;
|
401 |
|
|
reg [31:0] pfad_7,pfad_6,pfad_8,pfad_4a;
|
402 |
|
|
wire [31:0] pfad_4,pfad_5,pfad_11;
|
403 |
|
|
|
404 |
|
|
reg [31:0] bwd_daten1,bwd_daten2;
|
405 |
|
|
wire [31:0] addsub_q;
|
406 |
|
|
|
407 |
|
|
// +++++++++++++ Global Output Multiplexer ++++++++++++++++++++++++++++
|
408 |
|
|
|
409 |
11 |
ns32kum |
always @(OPCODE or pfad_4 or pfad_5 or pfad_6 or pfad_7 or pfad_8 or DP_OUT or FL or SFP_DAT or FSR or pfad_11)
|
410 |
9 |
ns32kum |
casex (OPCODE[7:3])
|
411 |
|
|
5'b0100_x : I_OUT = pfad_4;
|
412 |
|
|
5'b0101_x : I_OUT = pfad_5; // String opcodes
|
413 |
|
|
5'b0110_x : I_OUT = pfad_6;
|
414 |
|
|
5'b0111_x : I_OUT = pfad_7;
|
415 |
|
|
5'b1000_x : I_OUT = pfad_8;
|
416 |
|
|
5'b1001_0 : I_OUT = DP_OUT; // SP_FPU has higher priority ! LFSR has no output
|
417 |
|
|
// SFSR : ROUND,TRUNC,FLOOR Integer Data : SP or DP Block
|
418 |
|
|
5'b1001_1 : I_OUT = (OPCODE[2:1] == 2'b10) ? FSR : (FL ? SFP_DAT : DP_OUT);
|
419 |
|
|
5'b1011_x : I_OUT = pfad_11;
|
420 |
|
|
5'b1101_x : I_OUT = DP_OUT; // Coprocessor
|
421 |
|
|
default : I_OUT = 32'hxxxx_xxxx; // don't care
|
422 |
|
|
endcase
|
423 |
|
|
|
424 |
|
|
// ++++++++++++++ PSR Register : I P S U / N Z F V - L T C
|
425 |
|
|
// 11 10 9 8 7 6 5 4 3 2 1 0
|
426 |
|
|
|
427 |
|
|
reg [3:0] psr_high;
|
428 |
|
|
reg [7:0] psr_low,psr_new;
|
429 |
|
|
reg [11:0] push_psr; // true Register
|
430 |
|
|
reg [11:0] calc_psr; // only verilog case
|
431 |
|
|
reg [1:0] nl_int;
|
432 |
|
|
|
433 |
|
|
wire ld_psr_l,ld_psr_h,up_psr;
|
434 |
|
|
wire cmp_op,bit_op,ari_op,neg_op,ffs_op,str_op,chk_op,abs_op,rwv_op;
|
435 |
|
|
wire [1:0] fp_nz;
|
436 |
|
|
wire f_flag,z_flag;
|
437 |
|
|
wire [1:0] nl_flags;
|
438 |
|
|
wire over_flow,cy_out;
|
439 |
|
|
wire ffs_flag; // FLAG result of FFS
|
440 |
|
|
wire chk_flag; // FLAG result of CHECK
|
441 |
|
|
wire save_psr,pop_psr;
|
442 |
|
|
wire [4:0] selbits;
|
443 |
|
|
// Bits from DETOIP;
|
444 |
11 |
ns32kum |
wire cmps_op,ph_match,until,kill_opt,inss_op,exin_cmd,extract,bit_reg,kurz_st,dw_info,acb_reg,t2p;
|
445 |
9 |
ns32kum |
wire bcd_op,bcd_carry;
|
446 |
|
|
|
447 |
|
|
assign cmps_op = DETOIP[11]; // for CMPS
|
448 |
|
|
assign ph_match = DETOIP[10]; // MATCH phase
|
449 |
|
|
assign until = DETOIP[9]; // UNITL Flag for String
|
450 |
|
|
assign kill_opt = DETOIP[8]; // optimized execution of MOVS/MOVM
|
451 |
|
|
assign inss_op = DETOIP[7]; // 1=INSS
|
452 |
|
|
assign exin_cmd = DETOIP[6]; // for EXT/INS
|
453 |
|
|
assign extract = DETOIP[5] & exin_cmd; // 1=EXT
|
454 |
|
|
assign bit_reg = DETOIP[4]; // for Bit opcodes
|
455 |
|
|
assign kurz_st = DETOIP[3]; // for MOVM/CMPM
|
456 |
|
|
assign dw_info = DETOIP[2]; // at ADJSPi is SP=SRC2 always 32 Bit
|
457 |
|
|
assign acb_reg = DETOIP[1]; // suppresses Carry-Set at ACB
|
458 |
|
|
assign t2p = DETOIP[0]; // Pulse to Load Trace-Bit to Pending-Trace-Bit
|
459 |
|
|
|
460 |
|
|
assign bcd_op = OVF_BCD[1]; // ADDPi,SUBPi - from DP_FPU
|
461 |
|
|
assign bcd_carry = OVF_BCD[0];
|
462 |
|
|
|
463 |
|
|
assign ld_psr_l = ((WRADR == 6'h1D) | (WRADR == 6'h10)) & WREN; // Register PSR & UPSR
|
464 |
|
|
assign ld_psr_h = (WRADR == 6'h1D) & (BWD != 2'b00) & WREN; // Register PSR
|
465 |
|
|
// LD_OUT[1] is coming out of DECODER for this purpose
|
466 |
|
|
assign up_psr = bcd_op | ((cmp_op | bit_op | ari_op | neg_op | ffs_op | chk_op) & LD_OUT);
|
467 |
|
|
|
468 |
11 |
ns32kum |
assign cmp_op = (OPCODE == 8'h41) | ((OPCODE == 8'hB2) & (FL ? ~SP_CMP[2] : ~DP_CMP[2])); // CMPi or (CMPf & ~NAN)
|
469 |
|
|
assign bit_op = ((OPCODE[7:4] == 4'h6) & ((~OPCODE[3] & OPCODE[1]) | OPCODE[3:0] == 4'hE)) // the last term is for IBIT
|
470 |
9 |
ns32kum |
| (OPCODE == 8'h4D) | str_op | rwv_op; // TBIT or CMPS or RDVAL/WRVAL
|
471 |
11 |
ns32kum |
assign ari_op = (OPCODE[7:4] == 4'h4) & (OPCODE[1:0] == 2'b0) & ~dw_info; // ADDi,ADDCi,SUBi,SUBCi - special case ADJSPi no flags
|
472 |
9 |
ns32kum |
assign neg_op = (OPCODE[7:4] == 4'h6) & (OPCODE[3] & (OPCODE[1:0] == 2'b0)); // ABSi,NEGi
|
473 |
|
|
assign ffs_op = (OPCODE == 8'h85); // FFS
|
474 |
|
|
assign chk_op = (OPCODE == 8'h83); // CHECK
|
475 |
11 |
ns32kum |
assign str_op = (OPCODE[7:4] == 4'h5) & (OPCODE[3:2] == 2'b0) & ~kurz_st; // String-"S" opcodes : F-Flag to 0, at start always
|
476 |
9 |
ns32kum |
assign abs_op = (OPCODE == 8'h6C); // ABSi : Carry is not affected !
|
477 |
|
|
assign rwv_op = (OPCODE[7:4] == 4'hE) & (OPCODE[3:1] == 3'b0); // RDVAL + WRVAL
|
478 |
|
|
|
479 |
|
|
always @(bwd_daten1 or bwd_daten2 or addsub_q) // SRC1 > SRC2 ?
|
480 |
|
|
case ({bwd_daten2[31],bwd_daten1[31]})
|
481 |
|
|
2'b00 : nl_int = {addsub_q[31],addsub_q[31]}; // MSB = N , LSB = L
|
482 |
|
|
2'b01 : nl_int = { 1'b0 , 1'b1 };
|
483 |
|
|
2'b10 : nl_int = { 1'b1 , 1'b0 };
|
484 |
|
|
2'b11 : nl_int = {addsub_q[31],addsub_q[31]};
|
485 |
|
|
endcase
|
486 |
|
|
|
487 |
|
|
assign ACB_ZERO = (addsub_q == 32'h0); // is used for ACBi opcode too
|
488 |
11 |
ns32kum |
assign f_flag = str_op ? 1'b0 : (rwv_op ? RWVFLAG : (bit_op ? SRC2[selbits] : (acb_reg ? PSR[5] : over_flow)));
|
489 |
9 |
ns32kum |
assign fp_nz = FL ? SP_CMP[1:0] : DP_CMP[1:0];
|
490 |
|
|
assign z_flag = OPCODE[1] ? fp_nz[0] : ACB_ZERO;
|
491 |
|
|
assign nl_flags = OPCODE[1] ? {fp_nz[1],1'b0} : nl_int;
|
492 |
|
|
|
493 |
|
|
always @(*) // Bits : N Z F V - L T C
|
494 |
|
|
casex ({cmp_op,bcd_op,bit_op,(ffs_op | chk_op)})
|
495 |
11 |
ns32kum |
4'b0000 : psr_new = {PSR[7:6], f_flag,PSR[4:1],((acb_reg | abs_op) ? PSR[0] : cy_out)}; // arithmetic Op : CY and F
|
496 |
9 |
ns32kum |
4'b0001 : psr_new = {PSR[7:6],(ffs_op ? ffs_flag : chk_flag),PSR[4:0]}; // FFS or CHECK
|
497 |
|
|
4'b001x : psr_new = (cmps_op & str_op) ?
|
498 |
|
|
{2'b01, f_flag,PSR[4:3],1'b0,PSR[1:0]} // Init CMPS
|
499 |
|
|
: {PSR[7:6], f_flag,PSR[4:0]}; // Bit opcode
|
500 |
|
|
4'b01xx : psr_new = {PSR[7:6], 1'b0, PSR[4:1],bcd_carry}; // BCD opcode
|
501 |
|
|
4'b1xxx : psr_new = ph_match ?
|
502 |
|
|
{PSR[7:6], ~(ACB_ZERO ^ until), PSR[4:0]} // Until/While Option at String-"S" opcodes
|
503 |
|
|
: {nl_flags[1],z_flag,PSR[5:3], nl_flags[0],PSR[1:0]}; // CMP f or i
|
504 |
|
|
endcase
|
505 |
|
|
|
506 |
|
|
always @(save_psr or pop_psr or OPCODE or PSR or SRC1)
|
507 |
|
|
casex ({save_psr,pop_psr,OPCODE[6],OPCODE[2]})
|
508 |
11 |
ns32kum |
4'b10xx : calc_psr = PSR & {~OPCODE[0],11'h0ED}; // clear P S U V T and the I-Bit at Interrupt & ABORT
|
509 |
9 |
ns32kum |
4'b11xx : calc_psr = SRC1[27:16];
|
510 |
|
|
4'b0x00 : calc_psr = PSR & ~SRC1[11:0]; // BICPSR : Opcode = h32
|
511 |
|
|
4'b0x01 : calc_psr = PSR | SRC1[11:0]; // BISPSR h36
|
512 |
|
|
default : calc_psr = SRC1[11:0]; // LPR PSR h76
|
513 |
|
|
endcase
|
514 |
|
|
|
515 |
|
|
// Special case Exception Handling : Code x'89-x'8F
|
516 |
|
|
assign save_psr = (OPCODE[7:3] == 5'b1000_1);
|
517 |
|
|
assign pop_psr = (OPCODE[2:0] == 3'b000);
|
518 |
|
|
|
519 |
|
|
always @(posedge BCLK or negedge BRESET) // central memory for PSR low
|
520 |
|
|
if (!BRESET) psr_low <= 8'h0;
|
521 |
|
|
else
|
522 |
|
|
begin
|
523 |
|
|
if (ld_psr_l || save_psr) psr_low <= calc_psr[7:0];
|
524 |
|
|
else
|
525 |
|
|
if (up_psr) psr_low <= psr_new; // the Status result of a normal opcode
|
526 |
|
|
end
|
527 |
|
|
|
528 |
|
|
always @(posedge BCLK or negedge BRESET) // central memory for PSR high
|
529 |
|
|
if (!BRESET) psr_high <= 4'h0;
|
530 |
|
|
else
|
531 |
|
|
begin
|
532 |
|
|
if (ld_psr_h || save_psr) psr_high <= calc_psr[11:8]; // only at WORD access
|
533 |
|
|
else // t2p : copy T-Bit into P-Bit at the beginning of opcode
|
534 |
|
|
if (t2p) psr_high <= {psr_high[3],psr_low[1],psr_high[1:0]};
|
535 |
|
|
end
|
536 |
|
|
|
537 |
|
|
// Register for storage of PSR at Entry of Exception
|
538 |
11 |
ns32kum |
always @(posedge BCLK) if (save_psr) push_psr <= {PSR[11],(~OPCODE[1] & PSR[10]),PSR[9:0]}; // P-Flag modified
|
539 |
9 |
ns32kum |
|
540 |
|
|
assign PSR = {psr_high,psr_low};
|
541 |
|
|
|
542 |
|
|
// ++++++++++++++ Overflow Detection ++++++++++++++++++++++++++++++++++++++
|
543 |
|
|
|
544 |
|
|
reg ovf_mul,ovf_ash;
|
545 |
|
|
wire [31:0] shdat;
|
546 |
|
|
|
547 |
|
|
always @(posedge BCLK or negedge BRESET)
|
548 |
|
|
if (!BRESET) OV_FLAG <= 1'b0;
|
549 |
|
|
else
|
550 |
|
|
if (OVF_BCD[3]) OV_FLAG <= OVF_BCD[2]; // DEI,QUO,DIV
|
551 |
|
|
else
|
552 |
|
|
if (LD_OUT)
|
553 |
|
|
case (OPCODE)
|
554 |
|
|
8'h78 : OV_FLAG <= ovf_mul;
|
555 |
|
|
8'h61 : OV_FLAG <= ovf_ash;
|
556 |
|
|
8'h40 : OV_FLAG <= over_flow & acb_reg; // ADD Opcode at ACB
|
557 |
|
|
default : OV_FLAG <= 1'b0;
|
558 |
|
|
endcase
|
559 |
|
|
|
560 |
|
|
always @(BWD or MRESULT)
|
561 |
|
|
casex (BWD)
|
562 |
|
|
2'b00 : ovf_mul = ~((MRESULT[15:7] == 9'd0) | (MRESULT[15:7] == 9'h1FF));
|
563 |
|
|
2'b01 : ovf_mul = ~((MRESULT[31:15] == 17'd0) | (MRESULT[31:15] == 17'h1FFFF));
|
564 |
|
|
default : ovf_mul = ~((MRESULT[63:31] == 33'd0) | (MRESULT[63:31] == 33'h1FFFFFFFF));
|
565 |
|
|
endcase
|
566 |
|
|
|
567 |
|
|
always @(BWD or SRC2 or shdat)
|
568 |
|
|
casex (BWD)
|
569 |
|
|
2'b00 : ovf_ash = (SRC2[7] != shdat[7]);
|
570 |
|
|
2'b01 : ovf_ash = (SRC2[15] != shdat[15]);
|
571 |
|
|
default : ovf_ash = (SRC2[31] != shdat[31]);
|
572 |
|
|
endcase
|
573 |
|
|
|
574 |
|
|
// ++++++++++++++ Format 4 Opcodes : Basic Integer Opcodes, MOVi is special case +++++++++++++
|
575 |
|
|
|
576 |
|
|
reg cy_in;
|
577 |
|
|
reg get_psr,rd_psr,rd_dsr;
|
578 |
|
|
wire add_flag;
|
579 |
|
|
|
580 |
|
|
always @(BWD or SRC1)
|
581 |
|
|
casex (BWD)
|
582 |
|
|
2'b00 : bwd_daten1 = {{24{SRC1[7]}}, SRC1[7:0]}; // Sign Extension
|
583 |
|
|
2'b01 : bwd_daten1 = {{16{SRC1[15]}},SRC1[15:0]};
|
584 |
|
|
default : bwd_daten1 = SRC1;
|
585 |
|
|
endcase
|
586 |
|
|
|
587 |
11 |
ns32kum |
assign add_flag = ~OPCODE[3] & ~OPCODE[1] & ~OPCODE[0]; // Only ADDi and ADDCi otherwise subtract in SCHALE
|
588 |
9 |
ns32kum |
|
589 |
|
|
always @(PSR or OPCODE) // more effort due to ABSi und NEGi : Format 6
|
590 |
|
|
casex ({OPCODE[5],OPCODE[3:2]})
|
591 |
|
|
3'b000 : cy_in = OPCODE[0]; // ADD + CMP
|
592 |
|
|
3'b001 : cy_in = PSR[0]; // ADDC
|
593 |
|
|
3'b011 : cy_in = ~PSR[0]; // SUBC
|
594 |
|
|
default : cy_in = 1'b1; // SUB + ABS + NEG : BORROW must be 1 for normal Adder
|
595 |
|
|
endcase
|
596 |
|
|
|
597 |
11 |
ns32kum |
SCHALE addsub_ipfad (.dataa(bwd_daten2), .datab(bwd_daten1), .cin(cy_in), .add_sub(add_flag), .bwd(BWD),
|
598 |
9 |
ns32kum |
.result(addsub_q), .cout(cy_out), .overflow(over_flow) );
|
599 |
|
|
|
600 |
11 |
ns32kum |
always @(posedge BCLK) get_psr <= (RDAA == 8'h9D) | (RDAA == 8'h90) | (RDAA == 8'h93); // PSR or US or DSR is read
|
601 |
9 |
ns32kum |
always @(posedge BCLK) rd_psr <= (RDAA[1:0] == 2'b01);
|
602 |
|
|
always @(posedge BCLK) rd_dsr <= (RDAA[1:0] == 2'b11);
|
603 |
|
|
|
604 |
|
|
always @(OPCODE or SRC1 or SRC2 or get_psr or rd_psr or rd_dsr or DSR or PSR or ADDR)
|
605 |
|
|
casex (OPCODE[3:1])
|
606 |
|
|
3'b001 : pfad_4a = SRC2 & ~SRC1; // BIC
|
607 |
11 |
ns32kum |
3'bx10 : pfad_4a = get_psr ? {({4{rd_dsr}} & DSR),16'd0,({4{rd_psr}} & PSR[11:8]),({8{~rd_dsr}} & PSR[7:0])} : SRC1; // MOV
|
608 |
9 |
ns32kum |
3'b011 : pfad_4a = SRC2 | SRC1; // OR
|
609 |
|
|
3'b101 : pfad_4a = SRC2 & SRC1; // AND
|
610 |
|
|
3'b111 : pfad_4a = SRC2 ^ SRC1; // XOR
|
611 |
|
|
default : pfad_4a = ADDR; // ADDR, comes from ADDR_UNIT
|
612 |
|
|
endcase
|
613 |
|
|
|
614 |
|
|
assign pfad_4 = (OPCODE[1:0] == 2'b00) ? addsub_q : pfad_4a; // ADD,ADDC,SUB,SUBC have extra path
|
615 |
|
|
|
616 |
|
|
// ++++++++++++++ Format 5 Opcodes : Strings MOVS , CMPS und SKPS +++++++++++++++++++++++++++++++
|
617 |
|
|
|
618 |
|
|
reg [11:0] spointer,dpointer;
|
619 |
|
|
reg [9:0] todo;
|
620 |
|
|
reg [9:4] todo_reg;
|
621 |
13 |
ns32kum |
reg dis_opt;
|
622 |
|
|
wire [31:0] diff_poi;
|
623 |
9 |
ns32kum |
wire mehr,weiter,op_str,no_opt;
|
624 |
|
|
|
625 |
|
|
assign op_str = (OPCODE[7:3] == 5'b0101_0);
|
626 |
|
|
|
627 |
13 |
ns32kum |
assign diff_poi = SRC2 - SRC1; // Special Case
|
628 |
|
|
|
629 |
|
|
always @(posedge BCLK) if (op_str && OPCODE[2]) dis_opt <= (diff_poi[31:3] == 29'd0);
|
630 |
|
|
|
631 |
11 |
ns32kum |
// This logic is for detection if an accelerated MOVS/MOVM inside a page is possible - Backward is not possible
|
632 |
9 |
ns32kum |
always @(posedge BCLK)
|
633 |
|
|
if (op_str)
|
634 |
|
|
begin
|
635 |
|
|
spointer <= OPCODE[2] ? SRC1[11:0] : (spointer + {8'h00,todo[3:0]}); // Source
|
636 |
|
|
dpointer <= OPCODE[2] ? SRC2[11:0] : (dpointer + {8'h00,todo[3:0]}); // Destination
|
637 |
|
|
end
|
638 |
|
|
|
639 |
|
|
assign no_opt = OPCODE[1] | ((spointer[11:3] == 9'h1FF) & (spointer[2:0] != 3'b000))
|
640 |
13 |
ns32kum |
| kill_opt | ((dpointer[11:3] == 9'h1FF) & (dpointer[2:0] != 3'b000))
|
641 |
|
|
| dis_opt;
|
642 |
9 |
ns32kum |
|
643 |
13 |
ns32kum |
assign pfad_5 = SRC1 - {28'h0,todo_reg[7:4]};
|
644 |
9 |
ns32kum |
|
645 |
|
|
assign mehr = (pfad_5[31:4] != 28'h0);
|
646 |
|
|
|
647 |
|
|
always @(no_opt or BWD or mehr or pfad_5)
|
648 |
|
|
casex ({no_opt,BWD,mehr,pfad_5[3:0]})
|
649 |
|
|
8'b000_1xxxx : todo = 10'h388; // Byte
|
650 |
|
|
8'b000_01xxx : todo = 10'h388;
|
651 |
|
|
8'b000_001xx : todo = 10'h244;
|
652 |
|
|
8'b000_0001x : todo = 10'h122;
|
653 |
|
|
8'b000_00001 : todo = 10'h011;
|
654 |
|
|
//
|
655 |
|
|
8'b001_1xxxx : todo = 10'h348; // Word
|
656 |
|
|
8'b001_01xxx : todo = 10'h348;
|
657 |
|
|
8'b001_001xx : todo = 10'h348;
|
658 |
|
|
8'b001_0001x : todo = 10'h224;
|
659 |
|
|
8'b001_00001 : todo = 10'h112;
|
660 |
|
|
//
|
661 |
|
|
8'b01x_1xxxx : todo = 10'h328; // DWord
|
662 |
|
|
8'b01x_01xxx : todo = 10'h328;
|
663 |
|
|
8'b01x_001xx : todo = 10'h328;
|
664 |
|
|
8'b01x_0001x : todo = 10'h328;
|
665 |
|
|
8'b01x_00001 : todo = 10'h214;
|
666 |
|
|
//
|
667 |
|
|
8'b100_xxxxx : todo = 10'h011; // the opcodes CMPS and SKPS work on a single element
|
668 |
|
|
8'b101_xxxxx : todo = 10'h112;
|
669 |
|
|
8'b11x_xxxxx : todo = 10'h214;
|
670 |
|
|
default : todo = 10'hxxx;
|
671 |
|
|
endcase
|
672 |
|
|
|
673 |
13 |
ns32kum |
always @(posedge BCLK) if (op_str) todo_reg <= {todo[9:8],(OPCODE[2] ? 4'd0 : todo[7:4])}; // store for next phase 51
|
674 |
9 |
ns32kum |
|
675 |
|
|
assign weiter = mehr | (pfad_5[3:0] != 4'h0);
|
676 |
|
|
|
677 |
11 |
ns32kum |
assign STRING = {1'b0,ACB_ZERO,weiter,( op_str ? todo[9:8] : todo_reg[9:8] )}; // ACB_ZERO is delayed 1 cycle extern
|
678 |
9 |
ns32kum |
|
679 |
|
|
// +++++++++++++ Format 6 opcodes : ADDP + SUBP are done in DP_FPU ++++++++++++++++++++
|
680 |
|
|
|
681 |
|
|
wire rot,ash,lsh,eis_op;
|
682 |
|
|
wire [7:0] sh_count;
|
683 |
|
|
wire [4:0] shcode; // comes from SHIFTER
|
684 |
|
|
|
685 |
|
|
reg [4:0] disp_reg; // for EXT/INS
|
686 |
|
|
reg [2:0] offs_reg; // for INSS
|
687 |
|
|
wire exin_op,exin_op2;
|
688 |
|
|
wire [4:0] shval_ei;
|
689 |
|
|
wire [7:0] sh_exin;
|
690 |
|
|
|
691 |
|
|
assign rot = (OPCODE[3:0] == 4'h0);
|
692 |
|
|
assign ash = (OPCODE[3:0] == 4'h1);
|
693 |
11 |
ns32kum |
assign lsh = (OPCODE[3:1] == 3'b010); // 5 is LSH , but 4 is Trap(UND) and is used for right-shift of Offset !
|
694 |
9 |
ns32kum |
|
695 |
11 |
ns32kum |
assign eis_op = (OPCODE == 8'h73) | (OPCODE[7] & ~OPCODE[1] & inss_op); // EXTSi | INSSi at OPCODE=80h
|
696 |
9 |
ns32kum |
assign exin_op = exin_cmd & (OPCODE[7:4] == 4'h8); // identifies EXT/INS
|
697 |
|
|
assign exin_op2 = (exin_cmd | inss_op) & (OPCODE[7:4] == 4'h6); // identifies LSH
|
698 |
|
|
|
699 |
|
|
always @(posedge BCLK) disp_reg <= DISP; // at EXT the path via ADDR is already used for DEST !!!
|
700 |
|
|
always @(posedge BCLK) if (OPCODE[7]) offs_reg <= SRC1[7:5]; // for INSS , OPCODE=80h
|
701 |
|
|
|
702 |
|
|
// Byte for external Bit source, Double for Register
|
703 |
|
|
assign selbits = (bit_reg | eis_op | exin_op) ? (exin_op ? disp_reg : SRC1[4:0]) : {2'b00,BITSEL};
|
704 |
|
|
|
705 |
|
|
assign shval_ei = inss_op ? {2'b00,offs_reg} : (bit_reg ? SRC1[4:0] : {2'b00,SRC1[2:0]});
|
706 |
11 |
ns32kum |
assign sh_exin[4:0] = extract ? (5'd0 - shval_ei) : shval_ei; // EXT : right shift, INS : left shift
|
707 |
|
|
assign sh_exin[7:5] = (shval_ei == 5'd0) ? 3'b000 : {3{extract}}; // Special case : 0 has no negativ sign !
|
708 |
9 |
ns32kum |
|
709 |
|
|
// LSH shift by 16 bit to right
|
710 |
|
|
assign sh_count = (OPCODE[3:0] == 4'h4) ? 8'hF0 : (exin_op2 ? sh_exin : SRC1[7:0]);
|
711 |
|
|
|
712 |
11 |
ns32kum |
assign BMCODE = (bit_op | eis_op | exin_op) ? {(eis_op | exin_op),(bit_op | exin_op),selbits} : {2'b00,shcode};
|
713 |
9 |
ns32kum |
|
714 |
11 |
ns32kum |
SHIFTER shift_inst (.MASKE(BMASKE), .ROT(rot), .ASH(ash), .LSH(lsh), .SH_DAT(SRC2), .SH_VAL(sh_count),
|
715 |
9 |
ns32kum |
.MASK_SEL(shcode), .SIZE(BWD), .SH_OUT(shdat) );
|
716 |
|
|
|
717 |
|
|
always @(BWD or SRC2 or neg_op or dw_info)
|
718 |
|
|
casex ({neg_op,(dw_info | BWD[1]),BWD[0]}) // special case ADJSPi
|
719 |
|
|
3'b000 : bwd_daten2 = {{24{SRC2[7]}}, SRC2[7:0]}; // Sign Extension
|
720 |
|
|
3'b001 : bwd_daten2 = {{16{SRC2[15]}},SRC2[15:0]};
|
721 |
|
|
3'b1xx : bwd_daten2 = 32'h0; // is used for ABSi and NEGi
|
722 |
|
|
default : bwd_daten2 = SRC2;
|
723 |
|
|
endcase
|
724 |
|
|
|
725 |
|
|
always @(OPCODE or SRC2 or BMASKE or addsub_q or bwd_daten1 or SRC1 or shdat or DP_OUT)
|
726 |
|
|
casex (OPCODE[3:0])
|
727 |
|
|
4'b001x : pfad_6 = SRC2 & ~BMASKE; // CBIT & CBITI
|
728 |
|
|
4'b011x : pfad_6 = SRC2 | BMASKE; // SBIT & SBITI
|
729 |
|
|
4'b1000 : pfad_6 = addsub_q; // NEG
|
730 |
|
|
4'b1001 : pfad_6 = {SRC1[31:1],~SRC1[0]}; // NOT
|
731 |
|
|
4'b1010 : pfad_6 = SRC1; // Special case 6A : not used normal -> op_lmr !
|
732 |
|
|
4'b1100 : pfad_6 = bwd_daten1[31] ? addsub_q : SRC1; // ABS
|
733 |
|
|
4'b1101 : pfad_6 = ~SRC1; // COM
|
734 |
|
|
4'b1110 : pfad_6 = SRC2 ^ BMASKE; // IBIT
|
735 |
|
|
4'b1x11_: pfad_6 = DP_OUT; // ADDP + SUBP
|
736 |
|
|
default : pfad_6 = shdat; // Result of Barrelshifter
|
737 |
|
|
endcase
|
738 |
|
|
|
739 |
|
|
// ++++++++++++++ Format 7 : MUL +++++++++++++++++++++++
|
740 |
|
|
|
741 |
|
|
// This Condition-Code Decoder is written twice ... see DECODER
|
742 |
|
|
|
743 |
|
|
reg sc_bit;
|
744 |
|
|
wire sc_negativ,sc_zero,sc_flag,sc_larger,sc_carry_psr;
|
745 |
|
|
|
746 |
|
|
assign sc_negativ = PSR[7];
|
747 |
|
|
assign sc_zero = PSR[6];
|
748 |
|
|
assign sc_flag = PSR[5];
|
749 |
|
|
assign sc_larger = PSR[2];
|
750 |
|
|
assign sc_carry_psr = PSR[0];
|
751 |
|
|
|
752 |
|
|
always @(SRC1 or sc_zero or sc_carry_psr or sc_larger or sc_negativ or sc_flag)
|
753 |
|
|
case (SRC1[3:0])
|
754 |
|
|
4'h0 : sc_bit = sc_zero; // EQual
|
755 |
|
|
4'h1 : sc_bit = ~sc_zero; // Not Equal
|
756 |
|
|
4'h2 : sc_bit = sc_carry_psr; // Carry Set
|
757 |
|
|
4'h3 : sc_bit = ~sc_carry_psr; // Carry Clear
|
758 |
|
|
4'h4 : sc_bit = sc_larger; // Higher
|
759 |
|
|
4'h5 : sc_bit = ~sc_larger; // Lower or Same
|
760 |
|
|
4'h6 : sc_bit = sc_negativ; // Greater Than
|
761 |
|
|
4'h7 : sc_bit = ~sc_negativ; // Less or Equal
|
762 |
|
|
4'h8 : sc_bit = sc_flag; // Flag Set
|
763 |
|
|
4'h9 : sc_bit = ~sc_flag; // Flag Clear
|
764 |
|
|
4'hA : sc_bit = ~sc_larger & ~sc_zero; // LOwer
|
765 |
|
|
4'hB : sc_bit = sc_larger | sc_zero; // Higher or Same
|
766 |
|
|
4'hC : sc_bit = ~sc_negativ & ~sc_zero; // Less Than
|
767 |
|
|
4'hD : sc_bit = sc_negativ | sc_zero; // Greater or Equal
|
768 |
|
|
4'hE : sc_bit = 1'b1; // True
|
769 |
|
|
4'hF : sc_bit = 1'b0; // False
|
770 |
|
|
endcase
|
771 |
|
|
|
772 |
|
|
reg [3:0] bytes2anz;
|
773 |
|
|
wire [23:0] and_src1;
|
774 |
|
|
wire [31:0] movxz_dat;
|
775 |
|
|
wire [4:0] kurz_anz;
|
776 |
|
|
wire [31:0] ext_sh4,ext_sh2;
|
777 |
|
|
|
778 |
|
|
assign and_src1 = {{16{BWD[1]}},{8{BWD[0]}}} & SRC1[31:8]; // for MOVZ
|
779 |
|
|
|
780 |
|
|
assign movxz_dat = (OPCODE[1] ^ OPCODE[0]) ? {and_src1,SRC1[7:0]} : bwd_daten1; // MOVZ.. ?
|
781 |
|
|
|
782 |
|
|
always @(ADDR or BWD)
|
783 |
|
|
casex (BWD[1:0])
|
784 |
|
|
2'b00 : bytes2anz = ADDR[3:0];
|
785 |
|
|
2'b01 : bytes2anz = {1'b0,ADDR[3:1]};
|
786 |
|
|
2'b1x : bytes2anz = {2'b0,ADDR[3:2]};
|
787 |
|
|
endcase
|
788 |
|
|
|
789 |
|
|
assign kurz_anz = {1'b0,bytes2anz} + 5'h01; // count for MOVM/CMPM
|
790 |
|
|
|
791 |
|
|
assign ext_sh4 = SRC1[7] ? {4'h0,SRC2[31:4]} : SRC2; // EXTSi
|
792 |
|
|
assign ext_sh2 = SRC1[6] ? {2'b0,ext_sh4[31:2]} : ext_sh4;
|
793 |
|
|
|
794 |
|
|
always @(*)
|
795 |
|
|
casex (OPCODE[3:0])
|
796 |
|
|
4'b0011 : pfad_7 = (SRC1[5] ? {1'b0,ext_sh2[31:1]} : ext_sh2) & BMASKE; // EXTSi
|
797 |
|
|
4'b01xx : pfad_7 = movxz_dat; // MOVXBW, MOVZBW, MOVZiD, MOVXiD
|
798 |
|
|
4'b1000 : pfad_7 = MRESULT[31:0]; // MULi
|
799 |
|
|
4'b1010 : pfad_7 = {27'h0,(kurz_st ? kurz_anz : {4'h0,sc_bit})}; // SCond or start of MOVM/CMPM
|
800 |
|
|
default : pfad_7 = DP_OUT; // DIV etc.
|
801 |
|
|
endcase
|
802 |
|
|
|
803 |
|
|
// ++++++++++++++ Format 8 : multiple opcodes +++++++++++++++++++++++
|
804 |
|
|
|
805 |
|
|
reg chk_p1;
|
806 |
|
|
reg [31:0] ins_maske;
|
807 |
|
|
|
808 |
|
|
wire [4:0] ffs_out;
|
809 |
|
|
wire [15:0] low_bou,upp_bou,zeiger,chk_upp,chk_low;
|
810 |
|
|
wire flag_up,flag_lo;
|
811 |
|
|
|
812 |
|
|
FFS_LOGIK ffs_unit (.SRC1(SRC1), .SRC2(SRC2[4:0]), .BWD(BWD), .FLAG(ffs_flag), .DOUT(ffs_out) );
|
813 |
|
|
|
814 |
|
|
// CHECK : SRC1 are the Bounds
|
815 |
|
|
assign low_bou = BWD[0] ? SRC1[31:16] : {{8{SRC1[15]}},SRC1[15:8]};
|
816 |
|
|
assign upp_bou = BWD[0] ? SRC1[15:0] : {{8{SRC1[7]}}, SRC1[7:0]};
|
817 |
|
|
assign zeiger = BWD[0] ? SRC2[15:0] : {{8{SRC2[7]}}, SRC2[7:0]};
|
818 |
|
|
|
819 |
|
|
assign chk_upp = upp_bou - zeiger; // F=1 if upp_bou < zeiger
|
820 |
|
|
assign chk_low = zeiger - low_bou; // F=1 if zeiger < low_bou
|
821 |
|
|
|
822 |
|
|
assign flag_up = (upp_bou[15] == zeiger[15]) ? chk_upp[15] : upp_bou[15]; // See NL Definition
|
823 |
|
|
assign flag_lo = (low_bou[15] == zeiger[15]) ? chk_low[15] : zeiger[15];
|
824 |
|
|
|
825 |
|
|
always @(posedge BCLK) chk_p1 <= chk_op & BWD[1]; // CHECKD needs 2 cycles to execute
|
826 |
|
|
|
827 |
|
|
assign chk_flag = BWD[1] ? (chk_p1 ? (nl_int[1] | psr_low[5]) : nl_int[1]) : (flag_up | flag_lo);
|
828 |
|
|
|
829 |
|
|
always @(posedge BCLK) ins_maske <= shdat; // expensive solution in terms of LEs !
|
830 |
|
|
|
831 |
|
|
always @(*)
|
832 |
|
|
casex (OPCODE[3:0]) // CVTP (81) has no OPCODE !
|
833 |
11 |
ns32kum |
4'b000x : pfad_8 = (extract ? SRC2 : 32'hFFFF_FFFF) & BMASKE; // EXT, the other form is for INS to get the mask
|
834 |
|
|
4'b0010 : pfad_8 = (SRC1 & ins_maske) | (SRC2 & ~ins_maske); // INS ins_maske[] ? SRC1[] : SRC2[]
|
835 |
9 |
ns32kum |
4'b0011 : pfad_8 = BWD[1] ? addsub_q : {16'h0,chk_low};
|
836 |
|
|
4'b0101 : pfad_8 = {24'hxx_xxxx,3'b000,ffs_out};
|
837 |
11 |
ns32kum |
default : pfad_8 = {4'hx,push_psr,SRC1[15:0]}; // Opcode x'87-x'8F is used at CXP and therefore in Exception-Processing
|
838 |
9 |
ns32kum |
endcase
|
839 |
|
|
|
840 |
|
|
// ++++++++++++++ Format 11 : Floating-Point Datapath +++++++++++++++++++++++++++++++
|
841 |
|
|
|
842 |
|
|
assign pfad_11 = (OPCODE[1:0] == 2'b01) ?
|
843 |
|
|
{((OPCODE[3:2] == 2'b11) ? 1'b0 : (SRC1[31] ^ OPCODE[2])),SRC1[30:0]} // ABSf , NEGf + MOVf
|
844 |
|
|
: DP_OUT;
|
845 |
|
|
|
846 |
|
|
endmodule
|