1 |
2 |
rehayes |
////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// XGATE Coprocessor - XGATE RISC Processor Core
|
4 |
|
|
//
|
5 |
|
|
// Author: Bob Hayes
|
6 |
|
|
// rehayes@opencores.org
|
7 |
|
|
//
|
8 |
|
|
// Downloaded from: http://www.opencores.org/projects/xgate.....
|
9 |
|
|
//
|
10 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
11 |
|
|
// Copyright (c) 2009, Robert Hayes
|
12 |
|
|
//
|
13 |
|
|
// This source file is free software: you can redistribute it and/or modify
|
14 |
|
|
// it under the terms of the GNU Lesser General Public License as published
|
15 |
|
|
// by the Free Software Foundation, either version 3 of the License, or
|
16 |
|
|
// (at your option) any later version.
|
17 |
|
|
//
|
18 |
|
|
// Supplemental terms.
|
19 |
|
|
// * Redistributions of source code must retain the above copyright
|
20 |
|
|
// notice, this list of conditions and the following disclaimer.
|
21 |
|
|
// * Neither the name of the <organization> nor the
|
22 |
|
|
// names of its contributors may be used to endorse or promote products
|
23 |
|
|
// derived from this software without specific prior written permission.
|
24 |
|
|
//
|
25 |
|
|
// THIS SOFTWARE IS PROVIDED BY Robert Hayes ''AS IS'' AND ANY
|
26 |
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
27 |
|
|
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
28 |
|
|
// DISCLAIMED. IN NO EVENT SHALL Robert Hayes BE LIABLE FOR ANY
|
29 |
|
|
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
30 |
|
|
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
31 |
|
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
32 |
|
|
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
33 |
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
34 |
|
|
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
35 |
|
|
//
|
36 |
|
|
// You should have received a copy of the GNU General Public License
|
37 |
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
38 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
39 |
|
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
40 |
|
|
|
41 |
|
|
module xgate_risc #(parameter MAX_CHANNEL = 127) // Max XGATE Interrupt Channel Number
|
42 |
|
|
(
|
43 |
|
|
output reg [15:0] xgr1,
|
44 |
|
|
output reg [15:0] xgr2,
|
45 |
|
|
output reg [15:0] xgr3,
|
46 |
|
|
output reg [15:0] xgr4,
|
47 |
|
|
output reg [15:0] xgr5,
|
48 |
|
|
output reg [15:0] xgr6,
|
49 |
|
|
output reg [15:0] xgr7,
|
50 |
|
|
output [15:0] xgate_address,
|
51 |
|
|
output [15:0] write_mem_data, // Data for Memory write
|
52 |
34 |
rehayes |
output mem_access, //
|
53 |
2 |
rehayes |
output write_mem_strb_l, // Strobe for writing low data byte
|
54 |
|
|
output write_mem_strb_h, // Strobe for writing high data bye
|
55 |
|
|
output reg zero_flag,
|
56 |
|
|
output reg negative_flag,
|
57 |
|
|
output reg carry_flag,
|
58 |
|
|
output reg overflow_flag,
|
59 |
|
|
output reg [ 6:0] xgchid,
|
60 |
31 |
rehayes |
output reg [127:0] xgif_status, // XGATE Interrupt Flag
|
61 |
12 |
rehayes |
output xg_sw_irq, // Xgate Software interrupt
|
62 |
2 |
rehayes |
output [ 7:0] host_semap, // Semaphore status for host
|
63 |
12 |
rehayes |
output reg debug_active, // Latch to control debug mode in the RISC state machine
|
64 |
2 |
rehayes |
|
65 |
|
|
|
66 |
|
|
input [15:0] read_mem_data,
|
67 |
|
|
input [15:0] perif_data,
|
68 |
|
|
input risc_clk,
|
69 |
|
|
input async_rst_b,
|
70 |
5 |
rehayes |
input mem_req_ack, // Memory Bus available - data good
|
71 |
2 |
rehayes |
input xge, // XGATE Module Enable
|
72 |
31 |
rehayes |
input debug_mode_i, // Force RISC core into debug mode
|
73 |
15 |
rehayes |
input xgdbg_set, // Enter XGATE Debug Mode
|
74 |
|
|
input xgdbg_clear, // Leave XGATE Debug Mode
|
75 |
2 |
rehayes |
input xgss, // XGATE Single Step
|
76 |
|
|
input [15:1] xgvbr, // XGATE vector Base Address Register
|
77 |
|
|
input [ 6:0] int_req, // Encoded interrupt request
|
78 |
12 |
rehayes |
input xgie, // XGATE Interrupt Enable
|
79 |
|
|
input brk_irq_ena, // Enable BRK instruction to generate interrupt
|
80 |
17 |
rehayes |
input write_xgchid, // Write Strobe for XGCHID register
|
81 |
2 |
rehayes |
input write_xgsem, // Write Strobe for XGSEM register
|
82 |
|
|
input write_xgccr, // Write Strobe for XGATE Condition Code Register
|
83 |
41 |
rehayes |
input [ 1:0] write_xgpc, // Write Strobe for XGATE Program Counter
|
84 |
|
|
input [ 1:0] write_xgr7, // Write Strobe for XGATE Data Register R7
|
85 |
|
|
input [ 1:0] write_xgr6, // Write Strobe for XGATE Data Register R6
|
86 |
|
|
input [ 1:0] write_xgr5, // Write Strobe for XGATE Data Register R5
|
87 |
|
|
input [ 1:0] write_xgr4, // Write Strobe for XGATE Data Register R4
|
88 |
|
|
input [ 1:0] write_xgr3, // Write Strobe for XGATE Data Register R3
|
89 |
|
|
input [ 1:0] write_xgr2, // Write Strobe for XGATE Data Register R2
|
90 |
|
|
input [ 1:0] write_xgr1, // Write Strobe for XGATE Data Register R1
|
91 |
12 |
rehayes |
input xgsweif_c, // Clear Software Flag
|
92 |
2 |
rehayes |
input clear_xgif_7, // Strobe for decode to clear interrupt flag bank 7
|
93 |
|
|
input clear_xgif_6, // Strobe for decode to clear interrupt flag bank 6
|
94 |
|
|
input clear_xgif_5, // Strobe for decode to clear interrupt flag bank 5
|
95 |
|
|
input clear_xgif_4, // Strobe for decode to clear interrupt flag bank 4
|
96 |
|
|
input clear_xgif_3, // Strobe for decode to clear interrupt flag bank 3
|
97 |
|
|
input clear_xgif_2, // Strobe for decode to clear interrupt flag bank 2
|
98 |
|
|
input clear_xgif_1, // Strobe for decode to clear interrupt flag bank 1
|
99 |
|
|
input clear_xgif_0, // Strobe for decode to clear interrupt flag bank 0
|
100 |
|
|
input [15:0] clear_xgif_data // Data for decode to clear interrupt flag
|
101 |
|
|
);
|
102 |
|
|
|
103 |
26 |
rehayes |
integer j; // Loop counters for decode of XGATE Interrupt Register
|
104 |
2 |
rehayes |
integer k; // Loop counter for Bit Field Insert decode
|
105 |
26 |
rehayes |
integer bfi, bfii; // Loop counter for Bit Field Insert function
|
106 |
2 |
rehayes |
|
107 |
|
|
// State machine sequence
|
108 |
5 |
rehayes |
parameter [3:0] //synopsys enum state_info
|
109 |
|
|
IDLE = 4'b0000, // waiting for interrupt
|
110 |
|
|
CONT = 4'b0001, // Instruction processing state, first state
|
111 |
12 |
rehayes |
S_STALL = 4'b0010, // Simple Stall while updating PC after change of flow
|
112 |
40 |
rehayes |
W_STORE = 4'b1101, // Stall while doing memory word write access
|
113 |
|
|
W_LOAD = 4'b0011, // Stall while doing memory word read access
|
114 |
|
|
B_LOAD = 4'b0100, // Stall while doing memory byte read access
|
115 |
12 |
rehayes |
BREAK = 4'b0101, // Stop in this state after BRK instruction
|
116 |
|
|
BREAK_2 = 4'b0110, // Advance PC after Single Step command
|
117 |
|
|
LD_INST = 4'b0111, // Load Instruction in Debug mode
|
118 |
|
|
DEBUG = 4'b1000, // Stop in this state while waiting for debug commands
|
119 |
|
|
BOOT_1 = 4'b1001, //
|
120 |
|
|
BOOT_2 = 4'b1010, //
|
121 |
17 |
rehayes |
BOOT_3 = 4'b1011, //
|
122 |
|
|
CHG_CHID = 4'b1100;
|
123 |
12 |
rehayes |
|
124 |
|
|
|
125 |
2 |
rehayes |
// Semaphore states
|
126 |
|
|
parameter [1:0] NO_LOCK = 2'b00,
|
127 |
12 |
rehayes |
RISC_LOCK = 2'b10,
|
128 |
|
|
HOST_LOCK = 2'b11;
|
129 |
|
|
|
130 |
|
|
|
131 |
|
|
reg [ 3:0] cpu_state; // State register for instruction processing
|
132 |
5 |
rehayes |
reg [ 3:0] next_cpu_state; // Pseudo Register,
|
133 |
2 |
rehayes |
reg load_next_inst; // Pseudo Register,
|
134 |
12 |
rehayes |
reg [15:0] program_counter; // Program Counter register
|
135 |
40 |
rehayes |
wire [15:0] pc_sum; // Program Counter Adder
|
136 |
|
|
reg [15:0] pc_incr_mux; // Pseudo Register, mux to select the Program Counter Increment value
|
137 |
|
|
reg [15:0] next_pc; // Pseudo Register
|
138 |
|
|
wire [15:0] jump_offset; // Address offset to be added to pc on conditional branch instruction
|
139 |
|
|
wire [15:0] bra_offset; // Address offset to be added to pc on branch always instruction
|
140 |
2 |
rehayes |
reg [15:0] alu_result; // Pseudo Register,
|
141 |
12 |
rehayes |
reg [15:0] op_code; // Register for instruction being executed
|
142 |
2 |
rehayes |
reg ena_rd_low_byte; // Pseudo Register,
|
143 |
|
|
reg ena_rd_high_byte; // Pseudo Register,
|
144 |
|
|
|
145 |
12 |
rehayes |
reg data_access; // Pseudo Register, RAM access in proccess
|
146 |
|
|
reg data_write; // Pseudo Register, RAM access is write operation
|
147 |
|
|
reg data_word_op; // Pseudo Register, RAM access operation is 16 bits(word)
|
148 |
|
|
reg [15:0] data_address; // Pseudo Register, Address for RAM data read or write
|
149 |
|
|
reg [15:0] load_data; // Data captured from WISHBONE Master bus for Load instructions
|
150 |
|
|
|
151 |
|
|
reg [ 6:0] set_irq_flag; // Pseudo Register, pulse for setting irq output register
|
152 |
|
|
|
153 |
2 |
rehayes |
reg next_zero; // Pseudo Register,
|
154 |
|
|
reg next_negative; // Pseudo Register,
|
155 |
|
|
reg next_carry; // Pseudo Register,
|
156 |
|
|
reg next_overflow; // Pseudo Register,
|
157 |
17 |
rehayes |
|
158 |
12 |
rehayes |
reg op_code_error; // Pseudo Register,
|
159 |
|
|
reg software_error; // OP Code error, Address Error, BRK Error
|
160 |
|
|
wire addr_error; // Decode Addressing error
|
161 |
2 |
rehayes |
|
162 |
|
|
reg set_semaph; // Pseudo Register,
|
163 |
|
|
reg clear_semaph; // Pseudo Register,
|
164 |
|
|
reg [ 2:0] semaph_risc; // Pseudo Register,
|
165 |
|
|
reg [ 7:0] semap_risc_bit; // Pseudo Register,
|
166 |
|
|
wire [ 7:0] risc_semap; // Semaphore status bit for RISC
|
167 |
|
|
wire semaph_stat; // Return Status of Semaphore bit
|
168 |
12 |
rehayes |
|
169 |
2 |
rehayes |
reg [15:0] rd_data; // Pseudo Register,
|
170 |
|
|
reg [15:0] rs1_data; // Pseudo Register,
|
171 |
|
|
reg [15:0] rs2_data; // Pseudo Register,
|
172 |
12 |
rehayes |
|
173 |
2 |
rehayes |
wire [ 2:0] wrt_reg_sel;
|
174 |
12 |
rehayes |
reg sel_rd_field; // Pseudo Register,
|
175 |
|
|
reg wrt_sel_xgr1; // Pseudo Register,
|
176 |
|
|
reg wrt_sel_xgr2; // Pseudo Register,
|
177 |
|
|
reg wrt_sel_xgr3; // Pseudo Register,
|
178 |
|
|
reg wrt_sel_xgr4; // Pseudo Register,
|
179 |
|
|
reg wrt_sel_xgr5; // Pseudo Register,
|
180 |
|
|
reg wrt_sel_xgr6; // Pseudo Register,
|
181 |
|
|
reg wrt_sel_xgr7; // Pseudo Register,
|
182 |
|
|
|
183 |
31 |
rehayes |
reg [127:0] xgif_d;
|
184 |
12 |
rehayes |
|
185 |
2 |
rehayes |
reg [15:0] shift_in;
|
186 |
|
|
wire [15:0] shift_out;
|
187 |
|
|
wire shift_rollover;
|
188 |
|
|
reg shift_left;
|
189 |
|
|
reg [ 4:0] shift_ammount;
|
190 |
|
|
reg [15:0] shift_filler;
|
191 |
12 |
rehayes |
|
192 |
17 |
rehayes |
wire start_thread; // Signle to pop RISC core out of IDLE State
|
193 |
2 |
rehayes |
|
194 |
12 |
rehayes |
wire cpu_is_idle; // Processor is in the IDLE state
|
195 |
|
|
wire perif_wrt_ena; // Enable for Salve writes to CPU registers
|
196 |
|
|
|
197 |
|
|
reg xgss_edge; // Flop for edge detection
|
198 |
|
|
wire single_step; // Pulse to trigger a single instruction execution in debug mode
|
199 |
|
|
reg brk_set_dbg; // Pulse to set debug_active from instruction decoder
|
200 |
15 |
rehayes |
reg cmd_change_pc; // Debug write to PC register
|
201 |
12 |
rehayes |
|
202 |
31 |
rehayes |
reg [ 1:0] chid_sm_ns; // Pseudo Register for State Machine next state logic,
|
203 |
17 |
rehayes |
reg [ 1:0] chid_sm; //
|
204 |
|
|
wire chid_goto_idle; //
|
205 |
12 |
rehayes |
|
206 |
17 |
rehayes |
// Debug states for change CHID
|
207 |
|
|
parameter [1:0] CHID_IDLE = 2'b00,
|
208 |
|
|
CHID_TEST = 2'b10,
|
209 |
|
|
CHID_WAIT = 2'b11;
|
210 |
|
|
|
211 |
40 |
rehayes |
assign jump_offset = {{6{op_code[8]}}, op_code[8:0], 1'b0};
|
212 |
|
|
assign bra_offset = {{5{op_code[9]}}, op_code[9:0], 1'b0};
|
213 |
|
|
assign pc_sum = program_counter + pc_incr_mux;
|
214 |
17 |
rehayes |
|
215 |
2 |
rehayes |
assign xgate_address = data_access ? data_address : program_counter;
|
216 |
34 |
rehayes |
|
217 |
|
|
assign mem_access = data_access || load_next_inst;
|
218 |
17 |
rehayes |
|
219 |
12 |
rehayes |
// Generate an address for an op code fetch from an odd address or a word Load/Store from/to an odd address.
|
220 |
|
|
assign addr_error = xgate_address[0] && (load_next_inst || (data_access && data_word_op));
|
221 |
|
|
|
222 |
2 |
rehayes |
assign write_mem_strb_l = data_access && data_write && (data_word_op || !data_address[0]);
|
223 |
|
|
assign write_mem_strb_h = data_access && data_write && (data_word_op || data_address[0]);
|
224 |
|
|
assign write_mem_data = (write_mem_strb_l || write_mem_strb_h) ? rd_data : 16'b0;
|
225 |
12 |
rehayes |
|
226 |
17 |
rehayes |
assign start_thread = xge && (|int_req) && !debug_active;
|
227 |
12 |
rehayes |
|
228 |
|
|
assign cpu_is_idle = (cpu_state == IDLE);
|
229 |
15 |
rehayes |
assign perif_wrt_ena = (cpu_is_idle && ~xge) || debug_active;
|
230 |
12 |
rehayes |
|
231 |
2 |
rehayes |
// Decode register select for RD and RS
|
232 |
|
|
always @*
|
233 |
|
|
begin
|
234 |
26 |
rehayes |
case (op_code[10:8]) // synopsys parallel_case
|
235 |
2 |
rehayes |
3'b001 : rd_data = xgr1;
|
236 |
|
|
3'b010 : rd_data = xgr2;
|
237 |
|
|
3'b011 : rd_data = xgr3;
|
238 |
|
|
3'b100 : rd_data = xgr4;
|
239 |
|
|
3'b101 : rd_data = xgr5;
|
240 |
|
|
3'b110 : rd_data = xgr6;
|
241 |
|
|
3'b111 : rd_data = xgr7;
|
242 |
|
|
default : rd_data = 16'h0; // XGR0 is always Zero
|
243 |
|
|
endcase
|
244 |
|
|
end
|
245 |
|
|
|
246 |
|
|
assign wrt_reg_sel = sel_rd_field ? op_code[10:8] : op_code[4:2];
|
247 |
|
|
|
248 |
|
|
// Decode register write select for eather RD or RI/RS2
|
249 |
|
|
always @*
|
250 |
|
|
begin
|
251 |
15 |
rehayes |
wrt_sel_xgr1 = (cpu_state == BOOT_3);
|
252 |
2 |
rehayes |
wrt_sel_xgr2 = 1'b0;
|
253 |
|
|
wrt_sel_xgr3 = 1'b0;
|
254 |
|
|
wrt_sel_xgr4 = 1'b0;
|
255 |
|
|
wrt_sel_xgr5 = 1'b0;
|
256 |
|
|
wrt_sel_xgr6 = 1'b0;
|
257 |
12 |
rehayes |
wrt_sel_xgr7 = 1'b0;
|
258 |
26 |
rehayes |
case (wrt_reg_sel) // synopsys parallel_case
|
259 |
5 |
rehayes |
3'b001 : wrt_sel_xgr1 = mem_req_ack;
|
260 |
|
|
3'b010 : wrt_sel_xgr2 = mem_req_ack;
|
261 |
|
|
3'b011 : wrt_sel_xgr3 = mem_req_ack;
|
262 |
|
|
3'b100 : wrt_sel_xgr4 = mem_req_ack;
|
263 |
|
|
3'b101 : wrt_sel_xgr5 = mem_req_ack;
|
264 |
|
|
3'b110 : wrt_sel_xgr6 = mem_req_ack;
|
265 |
|
|
3'b111 : wrt_sel_xgr7 = mem_req_ack;
|
266 |
2 |
rehayes |
endcase
|
267 |
|
|
end
|
268 |
|
|
|
269 |
|
|
// Decode register select for RS1 and RB
|
270 |
|
|
always @*
|
271 |
26 |
rehayes |
case (op_code[7:5]) // synopsys parallel_case
|
272 |
2 |
rehayes |
3'b001 : rs1_data = xgr1;
|
273 |
|
|
3'b010 : rs1_data = xgr2;
|
274 |
|
|
3'b011 : rs1_data = xgr3;
|
275 |
|
|
3'b100 : rs1_data = xgr4;
|
276 |
|
|
3'b101 : rs1_data = xgr5;
|
277 |
|
|
3'b110 : rs1_data = xgr6;
|
278 |
|
|
3'b111 : rs1_data = xgr7;
|
279 |
|
|
default : rs1_data = 16'h0; // XGR0 is always Zero
|
280 |
|
|
endcase
|
281 |
|
|
|
282 |
|
|
// Decode register select for RS2 and RI
|
283 |
|
|
always @*
|
284 |
26 |
rehayes |
case (op_code[4:2]) // synopsys parallel_case
|
285 |
2 |
rehayes |
3'b001 : rs2_data = xgr1;
|
286 |
|
|
3'b010 : rs2_data = xgr2;
|
287 |
|
|
3'b011 : rs2_data = xgr3;
|
288 |
|
|
3'b100 : rs2_data = xgr4;
|
289 |
|
|
3'b101 : rs2_data = xgr5;
|
290 |
|
|
3'b110 : rs2_data = xgr6;
|
291 |
|
|
3'b111 : rs2_data = xgr7;
|
292 |
|
|
default : rs2_data = 16'h0; // XGR0 is always Zero
|
293 |
|
|
endcase
|
294 |
|
|
|
295 |
|
|
reg [15:0] bf_mux_mask; // Mask for controlling mux's in Bit Field Insert Instructions
|
296 |
|
|
// Decode mux select mask for Bit Field Insert Instructions
|
297 |
|
|
always @*
|
298 |
|
|
begin
|
299 |
|
|
k = 0;
|
300 |
|
|
while (k < 16)
|
301 |
|
|
begin
|
302 |
|
|
bf_mux_mask[k] = 1'b0;
|
303 |
|
|
if ((k >= rs2_data[3:0]) && (k <= rs2_data[3:0] + rs2_data[7:4]))
|
304 |
|
|
bf_mux_mask[k] = 1'b1;
|
305 |
|
|
k = k + 1;
|
306 |
|
|
end
|
307 |
|
|
end
|
308 |
|
|
|
309 |
12 |
rehayes |
// Software Error Interrupt Latch
|
310 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
311 |
|
|
if ( !async_rst_b )
|
312 |
|
|
software_error <= 1'b0;
|
313 |
|
|
else
|
314 |
17 |
rehayes |
software_error <= addr_error || op_code_error ||
|
315 |
12 |
rehayes |
(brk_set_dbg && brk_irq_ena) || (software_error && !xgsweif_c);
|
316 |
17 |
rehayes |
|
317 |
12 |
rehayes |
assign xg_sw_irq = software_error && xgie;
|
318 |
|
|
|
319 |
|
|
// Latch the debug state, set by eather xgdb or BRK instructions
|
320 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
321 |
|
|
if ( !async_rst_b )
|
322 |
|
|
debug_active <= 1'b0;
|
323 |
|
|
else
|
324 |
15 |
rehayes |
debug_active <= !xgdbg_clear && (xgdbg_set || brk_set_dbg || op_code_error || debug_active);
|
325 |
12 |
rehayes |
|
326 |
|
|
// Convert xgss (Single Step Pulse) to a one risc_clk wide pulse
|
327 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
328 |
|
|
if ( !async_rst_b )
|
329 |
|
|
xgss_edge <= 1'b0;
|
330 |
|
|
else
|
331 |
|
|
xgss_edge <= xgss;
|
332 |
|
|
|
333 |
|
|
assign single_step = xgss && !xgss_edge;
|
334 |
|
|
|
335 |
|
|
|
336 |
2 |
rehayes |
// CPU State Register
|
337 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
338 |
|
|
if ( !async_rst_b )
|
339 |
|
|
cpu_state <= IDLE;
|
340 |
|
|
else
|
341 |
5 |
rehayes |
cpu_state <= mem_req_ack ? next_cpu_state : cpu_state;
|
342 |
2 |
rehayes |
|
343 |
|
|
// CPU Instruction Register
|
344 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
345 |
|
|
if ( !async_rst_b )
|
346 |
|
|
op_code <= 16'h0000;
|
347 |
|
|
else
|
348 |
5 |
rehayes |
op_code <= (load_next_inst && mem_req_ack) ? read_mem_data : op_code;
|
349 |
12 |
rehayes |
|
350 |
2 |
rehayes |
// Active Channel Latch
|
351 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
352 |
|
|
if ( !async_rst_b )
|
353 |
|
|
xgchid <= 7'b0;
|
354 |
|
|
else
|
355 |
17 |
rehayes |
xgchid <= (write_xgchid && debug_active) ? perif_data[6:0] : ((cpu_is_idle && mem_req_ack) ? int_req : xgchid);
|
356 |
2 |
rehayes |
|
357 |
17 |
rehayes |
// Channel Change Debug state machine register
|
358 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
359 |
|
|
if ( !async_rst_b )
|
360 |
|
|
chid_sm <= CHID_IDLE;
|
361 |
|
|
else
|
362 |
|
|
chid_sm <= chid_sm_ns;
|
363 |
|
|
|
364 |
|
|
// Channel Change Debug next state
|
365 |
|
|
always @*
|
366 |
26 |
rehayes |
case (chid_sm) // synopsys parallel_case
|
367 |
17 |
rehayes |
CHID_IDLE:
|
368 |
|
|
if ( write_xgchid && debug_active )
|
369 |
|
|
chid_sm_ns = CHID_TEST;
|
370 |
|
|
CHID_TEST:
|
371 |
|
|
if ( !((cpu_state == IDLE) || (cpu_state == CHG_CHID)) && (|xgchid) )
|
372 |
|
|
chid_sm_ns = CHID_IDLE;
|
373 |
|
|
else
|
374 |
|
|
chid_sm_ns = CHID_WAIT;
|
375 |
|
|
CHID_WAIT:
|
376 |
|
|
if ( (cpu_state == IDLE) || (cpu_state == CHG_CHID) )
|
377 |
|
|
chid_sm_ns = CHID_IDLE;
|
378 |
|
|
else
|
379 |
|
|
chid_sm_ns = CHID_WAIT;
|
380 |
|
|
default : chid_sm_ns = CHID_IDLE;
|
381 |
|
|
endcase
|
382 |
|
|
|
383 |
|
|
assign chid_goto_idle = (chid_sm == CHID_WAIT);
|
384 |
|
|
|
385 |
2 |
rehayes |
// CPU Read Data Buffer Register
|
386 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
387 |
|
|
if ( !async_rst_b )
|
388 |
|
|
load_data <= 16'h0000;
|
389 |
|
|
else
|
390 |
5 |
rehayes |
load_data <= (data_access && !data_write && mem_req_ack) ? read_mem_data : load_data;
|
391 |
2 |
rehayes |
|
392 |
|
|
// Program Counter Register
|
393 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
394 |
|
|
if ( !async_rst_b )
|
395 |
|
|
program_counter <= 16'h0000;
|
396 |
|
|
else
|
397 |
41 |
rehayes |
program_counter <= (|write_xgpc && perif_wrt_ena) ?
|
398 |
|
|
{(write_xgpc[1] ? perif_data[15:8]: program_counter[15:8]),
|
399 |
|
|
(write_xgpc[0] ? perif_data[ 7:0]: program_counter[ 7:0])} :
|
400 |
|
|
(mem_req_ack ? next_pc : program_counter);
|
401 |
2 |
rehayes |
|
402 |
15 |
rehayes |
// Debug Change Program Counter Register
|
403 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
404 |
|
|
if ( !async_rst_b )
|
405 |
|
|
cmd_change_pc <= 1'b0;
|
406 |
|
|
else
|
407 |
41 |
rehayes |
cmd_change_pc <= |write_xgpc && perif_wrt_ena;
|
408 |
15 |
rehayes |
|
409 |
2 |
rehayes |
// ALU Flag Bits
|
410 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
411 |
|
|
if ( !async_rst_b )
|
412 |
|
|
begin
|
413 |
|
|
carry_flag <= 1'b0;
|
414 |
|
|
overflow_flag <= 1'b0;
|
415 |
|
|
zero_flag <= 1'b0;
|
416 |
|
|
negative_flag <= 1'b0;
|
417 |
|
|
end
|
418 |
|
|
else
|
419 |
|
|
begin
|
420 |
12 |
rehayes |
carry_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[0] : (mem_req_ack ? next_carry : carry_flag);
|
421 |
|
|
overflow_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[1] : (mem_req_ack ? next_overflow : overflow_flag);
|
422 |
|
|
zero_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[2] : (mem_req_ack ? next_zero : zero_flag);
|
423 |
|
|
negative_flag <= (write_xgccr && perif_wrt_ena) ? perif_data[3] : (mem_req_ack ? next_negative : negative_flag);
|
424 |
2 |
rehayes |
end
|
425 |
|
|
|
426 |
|
|
// Interrupt Flag next value
|
427 |
|
|
always @*
|
428 |
12 |
rehayes |
begin
|
429 |
31 |
rehayes |
xgif_d = 0;
|
430 |
12 |
rehayes |
j = 0;
|
431 |
|
|
while (j <= MAX_CHANNEL)
|
432 |
|
|
begin
|
433 |
31 |
rehayes |
xgif_d[j] = xgif_status[j] || (set_irq_flag == j);
|
434 |
12 |
rehayes |
j = j + 1;
|
435 |
|
|
end
|
436 |
|
|
if (clear_xgif_0)
|
437 |
31 |
rehayes |
xgif_d[15: 0] = ~clear_xgif_data & xgif_status[15: 0];
|
438 |
12 |
rehayes |
if (clear_xgif_1)
|
439 |
31 |
rehayes |
xgif_d[31:16] = ~clear_xgif_data & xgif_status[31:16];
|
440 |
12 |
rehayes |
if (clear_xgif_2)
|
441 |
31 |
rehayes |
xgif_d[47:32] = ~clear_xgif_data & xgif_status[47:32];
|
442 |
12 |
rehayes |
if (clear_xgif_3)
|
443 |
31 |
rehayes |
xgif_d[63:48] = ~clear_xgif_data & xgif_status[63:48];
|
444 |
12 |
rehayes |
if (clear_xgif_4)
|
445 |
31 |
rehayes |
xgif_d[79:64] = ~clear_xgif_data & xgif_status[79:64];
|
446 |
12 |
rehayes |
if (clear_xgif_5)
|
447 |
31 |
rehayes |
xgif_d[95:80] = ~clear_xgif_data & xgif_status[95:80];
|
448 |
12 |
rehayes |
if (clear_xgif_6)
|
449 |
31 |
rehayes |
xgif_d[111:96] = ~clear_xgif_data & xgif_status[111:96];
|
450 |
12 |
rehayes |
if (clear_xgif_7)
|
451 |
31 |
rehayes |
xgif_d[127:112] = ~clear_xgif_data & xgif_status[127:112];
|
452 |
12 |
rehayes |
end
|
453 |
2 |
rehayes |
|
454 |
|
|
// Interrupt Flag Registers
|
455 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
456 |
|
|
if ( !async_rst_b )
|
457 |
31 |
rehayes |
xgif_status <= 0;
|
458 |
2 |
rehayes |
else
|
459 |
31 |
rehayes |
xgif_status <= xgif_d;
|
460 |
2 |
rehayes |
|
461 |
|
|
|
462 |
|
|
// RISC Data Registers
|
463 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
464 |
|
|
if ( !async_rst_b )
|
465 |
|
|
begin
|
466 |
|
|
xgr1 <= 16'b0;
|
467 |
|
|
xgr2 <= 16'b0;
|
468 |
|
|
xgr3 <= 16'b0;
|
469 |
|
|
xgr4 <= 16'b0;
|
470 |
|
|
xgr5 <= 16'b0;
|
471 |
|
|
xgr6 <= 16'b0;
|
472 |
|
|
xgr7 <= 16'b0;
|
473 |
|
|
end
|
474 |
|
|
else
|
475 |
|
|
begin
|
476 |
41 |
rehayes |
xgr1 <= (|write_xgr1 && perif_wrt_ena) ?
|
477 |
|
|
{(write_xgr1[1] ? perif_data[15:8]: xgr1[15:8]),
|
478 |
|
|
(write_xgr1[0] ? perif_data[ 7:0]: xgr1[ 7:0])} :
|
479 |
2 |
rehayes |
{((wrt_sel_xgr1 && ena_rd_high_byte) ? alu_result[15:8] : xgr1[15:8]),
|
480 |
|
|
((wrt_sel_xgr1 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr1[ 7:0])};
|
481 |
41 |
rehayes |
xgr2 <= (|write_xgr2 && perif_wrt_ena) ?
|
482 |
|
|
{(write_xgr2[1] ? perif_data[15:8]: xgr2[15:8]),
|
483 |
|
|
(write_xgr2[0] ? perif_data[ 7:0]: xgr2[ 7:0])} :
|
484 |
2 |
rehayes |
{((wrt_sel_xgr2 && ena_rd_high_byte) ? alu_result[15:8] : xgr2[15:8]),
|
485 |
|
|
((wrt_sel_xgr2 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr2[ 7:0])};
|
486 |
41 |
rehayes |
xgr3 <= (|write_xgr3 && perif_wrt_ena) ?
|
487 |
|
|
{(write_xgr3[1] ? perif_data[15:8]: xgr3[15:8]),
|
488 |
|
|
(write_xgr3[0] ? perif_data[ 7:0]: xgr3[ 7:0])} :
|
489 |
2 |
rehayes |
{((wrt_sel_xgr3 && ena_rd_high_byte) ? alu_result[15:8] : xgr3[15:8]),
|
490 |
|
|
((wrt_sel_xgr3 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr3[ 7:0])};
|
491 |
41 |
rehayes |
xgr4 <= (|write_xgr4 && perif_wrt_ena) ?
|
492 |
|
|
{(write_xgr4[1] ? perif_data[15:8]: xgr4[15:8]),
|
493 |
|
|
(write_xgr4[0] ? perif_data[ 7:0]: xgr4[ 7:0])} :
|
494 |
2 |
rehayes |
{((wrt_sel_xgr4 && ena_rd_high_byte) ? alu_result[15:8] : xgr4[15:8]),
|
495 |
|
|
((wrt_sel_xgr4 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr4[ 7:0])};
|
496 |
41 |
rehayes |
xgr5 <= (|write_xgr5 && perif_wrt_ena) ?
|
497 |
|
|
{(write_xgr5[1] ? perif_data[15:8]: xgr5[15:8]),
|
498 |
|
|
(write_xgr5[0] ? perif_data[ 7:0]: xgr5[ 7:0])} :
|
499 |
2 |
rehayes |
{((wrt_sel_xgr5 && ena_rd_high_byte) ? alu_result[15:8] : xgr5[15:8]),
|
500 |
|
|
((wrt_sel_xgr5 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr5[ 7:0])};
|
501 |
41 |
rehayes |
xgr6 <= (|write_xgr6 && perif_wrt_ena) ?
|
502 |
|
|
{(write_xgr6[1] ? perif_data[15:8]: xgr6[15:8]),
|
503 |
|
|
(write_xgr6[0] ? perif_data[ 7:0]: xgr6[ 7:0])} :
|
504 |
2 |
rehayes |
{((wrt_sel_xgr6 && ena_rd_high_byte) ? alu_result[15:8] : xgr6[15:8]),
|
505 |
|
|
((wrt_sel_xgr6 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr6[ 7:0])};
|
506 |
41 |
rehayes |
xgr7 <= (|write_xgr7 && perif_wrt_ena) ?
|
507 |
|
|
{(write_xgr7[1] ? perif_data[15:8]: xgr7[15:8]),
|
508 |
|
|
(write_xgr7[0] ? perif_data[ 7:0]: xgr7[ 7:0])} :
|
509 |
2 |
rehayes |
{((wrt_sel_xgr7 && ena_rd_high_byte) ? alu_result[15:8] : xgr7[15:8]),
|
510 |
|
|
((wrt_sel_xgr7 && ena_rd_low_byte) ? alu_result[ 7:0] : xgr7[ 7:0])};
|
511 |
|
|
end
|
512 |
|
|
|
513 |
|
|
// V Ñ Vector fetch: always an aligned word read, lasts for at least one RISC core cycle
|
514 |
|
|
// P Ñ Program word fetch: always an aligned word read, lasts for at least one RISC core cycle
|
515 |
|
|
// r Ñ 8-bit data read: lasts for at least one RISC core cycle
|
516 |
|
|
// R Ñ 16-bit data read: lasts for at least one RISC core cycle
|
517 |
|
|
// w Ñ 8-bit data write: lasts for at least one RISC core cycle
|
518 |
|
|
// W Ñ 16-bit data write: lasts for at least one RISC core cycle
|
519 |
|
|
// A Ñ Alignment cycle: no read or write, lasts for zero or one RISC core cycles
|
520 |
|
|
// f Ñ Free cycle: no read or write, lasts for one RISC core cycles
|
521 |
|
|
// Special Cases
|
522 |
|
|
// PP/P Ñ Branch: PP if branch taken, P if not taken
|
523 |
|
|
|
524 |
|
|
always @*
|
525 |
|
|
begin
|
526 |
|
|
ena_rd_low_byte = 1'b0;
|
527 |
|
|
ena_rd_high_byte = 1'b0;
|
528 |
|
|
|
529 |
12 |
rehayes |
next_cpu_state = debug_active ? LD_INST : CONT;
|
530 |
2 |
rehayes |
load_next_inst = 1'b1;
|
531 |
40 |
rehayes |
pc_incr_mux = 16'h0002; // Verilog Instruction order dependent
|
532 |
|
|
next_pc = pc_sum; // ""
|
533 |
2 |
rehayes |
|
534 |
|
|
next_zero = zero_flag;
|
535 |
|
|
next_negative = negative_flag;
|
536 |
|
|
next_carry = carry_flag;
|
537 |
|
|
next_overflow = overflow_flag;
|
538 |
|
|
|
539 |
12 |
rehayes |
brk_set_dbg = 1'b0;
|
540 |
|
|
op_code_error = 1'b0;
|
541 |
|
|
|
542 |
2 |
rehayes |
alu_result = 16'h0000;
|
543 |
|
|
sel_rd_field = 1'b1;
|
544 |
12 |
rehayes |
|
545 |
2 |
rehayes |
data_access = 1'b0;
|
546 |
|
|
data_word_op = 1'b0;
|
547 |
12 |
rehayes |
data_write = 1'b0;
|
548 |
2 |
rehayes |
data_address = 16'h0000;
|
549 |
|
|
|
550 |
|
|
shift_left = 1'b0;
|
551 |
|
|
shift_ammount = 5'b0_0000;
|
552 |
|
|
shift_filler = 16'h0000;
|
553 |
|
|
shift_in = rd_data;
|
554 |
12 |
rehayes |
|
555 |
2 |
rehayes |
set_irq_flag = 7'b0;
|
556 |
12 |
rehayes |
|
557 |
2 |
rehayes |
set_semaph = 1'b0;
|
558 |
|
|
clear_semaph = 1'b0;
|
559 |
|
|
semaph_risc = 3'b0;
|
560 |
|
|
|
561 |
|
|
casez ({cpu_state, op_code})
|
562 |
|
|
|
563 |
|
|
{IDLE, 16'b????????????????} :
|
564 |
|
|
begin
|
565 |
|
|
next_cpu_state = start_thread ? BOOT_1 : IDLE;
|
566 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
567 |
|
|
next_pc = pc_sum;
|
568 |
2 |
rehayes |
load_next_inst = 1'b0;
|
569 |
|
|
end
|
570 |
|
|
|
571 |
17 |
rehayes |
{CHG_CHID, 16'b????????????????} :
|
572 |
|
|
begin
|
573 |
|
|
if (!xge)
|
574 |
|
|
next_cpu_state = IDLE;
|
575 |
|
|
else if (single_step || !debug_active)
|
576 |
|
|
next_cpu_state = BOOT_1;
|
577 |
|
|
else
|
578 |
|
|
next_cpu_state = CHG_CHID;
|
579 |
|
|
|
580 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
581 |
|
|
next_pc = pc_sum;
|
582 |
17 |
rehayes |
load_next_inst = 1'b0;
|
583 |
|
|
end
|
584 |
|
|
|
585 |
2 |
rehayes |
// Output RAM address for Program Counter
|
586 |
|
|
{BOOT_1, 16'b????????????????} :
|
587 |
|
|
begin
|
588 |
|
|
next_cpu_state = BOOT_2;
|
589 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
590 |
|
|
next_pc = pc_sum;
|
591 |
2 |
rehayes |
load_next_inst = 1'b0;
|
592 |
|
|
data_access = 1'b1;
|
593 |
|
|
data_word_op = 1'b1;
|
594 |
|
|
data_address = {xgvbr, 1'b0} + {7'b0, xgchid, 2'b0};
|
595 |
|
|
end
|
596 |
|
|
|
597 |
|
|
// Load PC value from data buffer register
|
598 |
|
|
// Output RAM address for initial variable pointer
|
599 |
|
|
{BOOT_2, 16'b????????????????} :
|
600 |
|
|
begin
|
601 |
|
|
next_cpu_state = BOOT_3;
|
602 |
|
|
next_pc = load_data;
|
603 |
|
|
load_next_inst = 1'b0;
|
604 |
|
|
data_access = 1'b1;
|
605 |
|
|
data_word_op = 1'b1;
|
606 |
|
|
data_address = {xgvbr, 1'b0} + {7'b0, xgchid, 2'b0} + 2;
|
607 |
|
|
end
|
608 |
|
|
|
609 |
|
|
// Load R1 with initial variable pointer from data buffer register
|
610 |
|
|
// Load first instruction to op_code register
|
611 |
|
|
// Increment Program Counter
|
612 |
|
|
{BOOT_3, 16'b????????????????} :
|
613 |
|
|
begin
|
614 |
|
|
next_cpu_state = CONT;
|
615 |
|
|
ena_rd_low_byte = 1'b1;
|
616 |
|
|
ena_rd_high_byte = 1'b1;
|
617 |
|
|
alu_result = load_data;
|
618 |
|
|
end
|
619 |
|
|
|
620 |
12 |
rehayes |
{BREAK, 16'b????????????????} :
|
621 |
|
|
begin
|
622 |
17 |
rehayes |
if (!xge)
|
623 |
|
|
next_cpu_state = IDLE;
|
624 |
|
|
else if (single_step || !debug_active)
|
625 |
|
|
next_cpu_state = BREAK_2;
|
626 |
|
|
else if (chid_goto_idle)
|
627 |
|
|
next_cpu_state = CHG_CHID;
|
628 |
|
|
else
|
629 |
|
|
next_cpu_state = BREAK;
|
630 |
12 |
rehayes |
load_next_inst = 1'b0;
|
631 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
632 |
|
|
next_pc = pc_sum;
|
633 |
12 |
rehayes |
end
|
634 |
|
|
|
635 |
|
|
{BREAK_2, 16'b????????????????} :
|
636 |
|
|
begin
|
637 |
|
|
next_cpu_state = LD_INST;
|
638 |
|
|
load_next_inst = 1'b0;
|
639 |
|
|
end
|
640 |
|
|
|
641 |
|
|
{LD_INST, 16'b????????????????} :
|
642 |
|
|
begin
|
643 |
|
|
next_cpu_state = DEBUG;
|
644 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
645 |
|
|
next_pc = pc_sum;
|
646 |
12 |
rehayes |
end
|
647 |
|
|
|
648 |
2 |
rehayes |
{DEBUG, 16'b????????????????} :
|
649 |
|
|
begin
|
650 |
17 |
rehayes |
if (!xge)
|
651 |
|
|
next_cpu_state = IDLE;
|
652 |
|
|
else if (single_step || !debug_active)
|
653 |
|
|
next_cpu_state = CONT;
|
654 |
|
|
else if (cmd_change_pc)
|
655 |
|
|
next_cpu_state = LD_INST;
|
656 |
|
|
else if (chid_goto_idle)
|
657 |
|
|
next_cpu_state = CHG_CHID;
|
658 |
|
|
else
|
659 |
|
|
next_cpu_state = DEBUG;
|
660 |
|
|
|
661 |
15 |
rehayes |
load_next_inst = cmd_change_pc;
|
662 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
663 |
|
|
next_pc = pc_sum;
|
664 |
2 |
rehayes |
end
|
665 |
|
|
|
666 |
12 |
rehayes |
// Pause here for program counter change of flow or memory write access
|
667 |
5 |
rehayes |
// Load next instruction and increment PC
|
668 |
12 |
rehayes |
// Default next_cpu_state is CONT
|
669 |
5 |
rehayes |
{S_STALL, 16'b????????????????} :
|
670 |
|
|
begin
|
671 |
|
|
end
|
672 |
|
|
|
673 |
|
|
// Pause here for memory read word access
|
674 |
|
|
// Load next instruction and increment PC
|
675 |
40 |
rehayes |
{W_LOAD, 16'b????????????????} :
|
676 |
5 |
rehayes |
begin
|
677 |
40 |
rehayes |
// alu_result = read_mem_data;
|
678 |
5 |
rehayes |
alu_result = load_data;
|
679 |
|
|
ena_rd_low_byte = 1'b1;
|
680 |
|
|
ena_rd_high_byte = 1'b1;
|
681 |
|
|
end
|
682 |
|
|
|
683 |
|
|
// Pause here for memory read byte access
|
684 |
|
|
// Load next instruction and increment PC
|
685 |
40 |
rehayes |
{B_LOAD, 16'b????????????????} :
|
686 |
5 |
rehayes |
begin
|
687 |
40 |
rehayes |
// alu_result = {8'h00, read_mem_data[15:8]};
|
688 |
5 |
rehayes |
alu_result = {8'h00, load_data[15:8]};
|
689 |
|
|
ena_rd_low_byte = 1'b1;
|
690 |
|
|
ena_rd_high_byte = 1'b1;
|
691 |
|
|
end
|
692 |
|
|
|
693 |
2 |
rehayes |
// -----------------------------------------------------------------------
|
694 |
|
|
// Instruction Group -- Return to Scheduler and Others
|
695 |
|
|
// -----------------------------------------------------------------------
|
696 |
|
|
|
697 |
|
|
// Instruction = BRK, Op Code = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
698 |
|
|
// Cycles - PAff
|
699 |
|
|
{CONT, 16'b0000000000000000} :
|
700 |
|
|
begin
|
701 |
12 |
rehayes |
next_cpu_state = BREAK;
|
702 |
40 |
rehayes |
pc_incr_mux = 16'hfffe; // equals -2
|
703 |
|
|
next_pc = pc_sum;
|
704 |
2 |
rehayes |
load_next_inst = 1'b0;
|
705 |
12 |
rehayes |
brk_set_dbg = 1'b1;
|
706 |
2 |
rehayes |
end
|
707 |
|
|
|
708 |
|
|
// Instruction = NOP, Op Code = 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
|
709 |
|
|
{CONT, 16'b0000000100000000} :
|
710 |
|
|
begin
|
711 |
|
|
end
|
712 |
|
|
|
713 |
|
|
// Instruction = RTS, Op Code = 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
|
714 |
|
|
// Cycles - PA
|
715 |
|
|
{CONT, 16'b0000001000000000} :
|
716 |
|
|
begin
|
717 |
|
|
next_cpu_state = IDLE;
|
718 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
719 |
|
|
next_pc = pc_sum;
|
720 |
2 |
rehayes |
load_next_inst = 1'b0;
|
721 |
|
|
end
|
722 |
|
|
|
723 |
|
|
// Instruction = SIF, Op Code = 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0
|
724 |
|
|
// Sets the Interrupt Flag of the current channel (XGCHID) will be set.
|
725 |
|
|
// Cycles - PA
|
726 |
|
|
{CONT, 16'b0000001100000000} :
|
727 |
|
|
begin
|
728 |
|
|
set_irq_flag = xgchid;
|
729 |
|
|
end
|
730 |
|
|
|
731 |
|
|
// -----------------------------------------------------------------------
|
732 |
|
|
// Instruction Group -- Semaphore Instructions
|
733 |
|
|
// -----------------------------------------------------------------------
|
734 |
|
|
|
735 |
|
|
// Instruction = CSEM IMM3, Op Code = 0 0 0 0 0 IMM3 1 1 1 1 0 0 0 0
|
736 |
|
|
// Unlocks a semaphore that was locked by the RISC core.
|
737 |
|
|
// Cycles - PA
|
738 |
|
|
{CONT, 16'b00000???11110000} :
|
739 |
|
|
begin
|
740 |
|
|
clear_semaph = 1'b1;
|
741 |
|
|
semaph_risc = op_code[10:8];
|
742 |
|
|
end
|
743 |
|
|
|
744 |
|
|
// Instruction = CSEM RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 0 0 1
|
745 |
|
|
// Unlocks a semaphore that was locked by the RISC core.
|
746 |
|
|
// In monadic address mode, bits RS[2:0] select the semaphore to be cleared.
|
747 |
|
|
// Cycles - PA
|
748 |
|
|
{CONT, 16'b00000???11110001} :
|
749 |
|
|
begin
|
750 |
|
|
clear_semaph = 1'b1;
|
751 |
|
|
semaph_risc = rd_data[2:0];
|
752 |
|
|
end
|
753 |
|
|
|
754 |
|
|
// Instruction = SSEM IMM3, Op Code = 0 0 0 0 0 IMM3 1 1 1 1 0 0 1 0
|
755 |
|
|
// Attempts to set a semaphore. The state of the semaphore will be stored in the Carry-Flag:
|
756 |
|
|
// 1 = Semaphore is locked by the RISC core
|
757 |
|
|
// 0 = Semaphore is locked by the S12X_CPU
|
758 |
|
|
// Cycles - PA
|
759 |
|
|
{CONT, 16'b00000???11110010} :
|
760 |
|
|
begin
|
761 |
|
|
set_semaph = 1'b1;
|
762 |
|
|
semaph_risc = op_code[10:8];
|
763 |
|
|
|
764 |
|
|
next_carry = semaph_stat;
|
765 |
|
|
end
|
766 |
|
|
|
767 |
|
|
// Instruction = SSEM RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 0 1 1
|
768 |
|
|
// Attempts to set a semaphore. The state of the semaphore will be stored in the Carry-Flag:
|
769 |
|
|
// 1 = Semaphore is locked by the RISC core
|
770 |
|
|
// 0 = Semaphore is locked by the S12X_CPU
|
771 |
|
|
// In monadic address mode, bits RS[2:0] select the semaphore to be set.
|
772 |
|
|
// Cycles - PA
|
773 |
|
|
{CONT, 16'b00000???11110011} :
|
774 |
|
|
begin
|
775 |
|
|
set_semaph = 1'b1;
|
776 |
|
|
semaph_risc = rd_data[2:0];
|
777 |
|
|
|
778 |
|
|
next_carry = semaph_stat;
|
779 |
|
|
end
|
780 |
|
|
|
781 |
|
|
// -----------------------------------------------------------------------
|
782 |
|
|
// Instruction Group -- Single Register Instructions
|
783 |
|
|
// -----------------------------------------------------------------------
|
784 |
|
|
|
785 |
|
|
// Instruction = SEX RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 0 0
|
786 |
|
|
// SEX - Sign Extend Byte to Word
|
787 |
|
|
// Cycles - P
|
788 |
|
|
{CONT, 16'b00000???11110100} :
|
789 |
|
|
begin
|
790 |
|
|
ena_rd_high_byte = 1'b1;
|
791 |
|
|
|
792 |
|
|
alu_result = {{8{rd_data[7]}}, rd_data[7:0]};
|
793 |
|
|
next_zero = !(|alu_result);
|
794 |
|
|
next_negative = alu_result[15];
|
795 |
|
|
next_overflow = 1'b0;
|
796 |
|
|
end
|
797 |
|
|
|
798 |
|
|
// Instruction = PAR RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 0 1
|
799 |
|
|
// PAR - Calculate Parity
|
800 |
|
|
// Set Carry Flag on odd number of bits
|
801 |
|
|
// Cycles - P
|
802 |
|
|
{CONT, 16'b00000???11110101} :
|
803 |
|
|
begin
|
804 |
|
|
next_zero = !(|rd_data);
|
805 |
|
|
next_negative = 1'b0;
|
806 |
|
|
next_carry = ^rd_data;
|
807 |
|
|
next_overflow = 1'b0;
|
808 |
|
|
end
|
809 |
|
|
|
810 |
|
|
// Instruction = JAL RD, Op Code = 0 0 0 0 0 RD 1 1 1 1 0 1 1 0
|
811 |
|
|
// Jump And Link
|
812 |
|
|
// PC + $0002 => RD; RD => PC
|
813 |
|
|
// Jumps to the address stored in RD and saves the return address in RD.
|
814 |
|
|
// Cycles - PP
|
815 |
|
|
{CONT, 16'b00000???11110110} :
|
816 |
|
|
begin
|
817 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
818 |
2 |
rehayes |
load_next_inst = 1'b0;
|
819 |
|
|
ena_rd_low_byte = 1'b1;
|
820 |
|
|
ena_rd_high_byte = 1'b1;
|
821 |
|
|
alu_result = program_counter;
|
822 |
|
|
next_pc = rd_data;
|
823 |
|
|
end
|
824 |
|
|
|
825 |
|
|
// Instruction = SIF RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 0 1 1 1
|
826 |
|
|
// Sets the Interrupt Flag associated with the channel id number
|
827 |
|
|
// contained in RS[6:0] is set. The content of RS[15:7] is ignored
|
828 |
|
|
// Cycles - P
|
829 |
|
|
{CONT, 16'b00000???11110111} :
|
830 |
|
|
begin
|
831 |
|
|
set_irq_flag = rd_data[6:0];
|
832 |
|
|
end
|
833 |
|
|
|
834 |
|
|
// -----------------------------------------------------------------------
|
835 |
|
|
// Instruction Group -- Special Move instructions
|
836 |
|
|
// -----------------------------------------------------------------------
|
837 |
|
|
|
838 |
|
|
// Instruction = TFR RD,CCR, Op Code = 0 0 0 0 0 RD 1 1 1 1 1 0 0 0
|
839 |
|
|
// Transfer from and to Special Registers
|
840 |
|
|
// TFR RD,CCR: CCR => RD[3:0], 0 => RD[15:4]
|
841 |
|
|
// Cycles - P
|
842 |
|
|
{CONT, 16'b00000???11111000} :
|
843 |
|
|
begin
|
844 |
|
|
ena_rd_low_byte = 1'b1;
|
845 |
|
|
ena_rd_high_byte = 1'b1;
|
846 |
|
|
alu_result = {12'b0, negative_flag, zero_flag, overflow_flag, carry_flag};
|
847 |
|
|
end
|
848 |
|
|
|
849 |
|
|
// Instruction = TFR CCR,RS, Op Code = 0 0 0 0 0 RS 1 1 1 1 1 0 0 1
|
850 |
|
|
// Transfer from and to Special Registers
|
851 |
|
|
// TFR CCR,RD: RD[3:0] => CCR
|
852 |
|
|
// Cycles - P
|
853 |
|
|
{CONT, 16'b00000???11111001} :
|
854 |
|
|
begin
|
855 |
|
|
next_negative = rd_data[3];
|
856 |
|
|
next_zero = rd_data[2];
|
857 |
|
|
next_overflow = rd_data[1];
|
858 |
|
|
next_carry = rd_data[0];
|
859 |
|
|
end
|
860 |
|
|
|
861 |
|
|
// Instruction = TFR RD,PC, Op Code = 0 0 0 0 0 RD 1 1 1 1 1 0 1 0
|
862 |
|
|
// Transfer from and to Special Registers
|
863 |
|
|
// TFR RD,PC: PC+4 => RD
|
864 |
|
|
// Cycles - P
|
865 |
|
|
{CONT, 16'b00000???11111010} :
|
866 |
|
|
begin
|
867 |
|
|
ena_rd_low_byte = 1'b1;
|
868 |
|
|
ena_rd_high_byte = 1'b1;
|
869 |
|
|
alu_result = next_pc;
|
870 |
|
|
end
|
871 |
|
|
|
872 |
|
|
// -----------------------------------------------------------------------
|
873 |
|
|
// Instruction Group -- Shift instructions Dyadic
|
874 |
|
|
// -----------------------------------------------------------------------
|
875 |
|
|
|
876 |
|
|
// Instruction = BFFO RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 0 0
|
877 |
|
|
// BFFO - Bit Field Find First One
|
878 |
|
|
// FirstOne (RS) => RD
|
879 |
|
|
// Cycles - P
|
880 |
|
|
{CONT, 16'b00001??????10000} :
|
881 |
|
|
begin
|
882 |
|
|
ena_rd_low_byte = 1'b1;
|
883 |
|
|
ena_rd_high_byte = 1'b1;
|
884 |
|
|
|
885 |
26 |
rehayes |
casez (rs1_data) // synopsys parallel_case
|
886 |
2 |
rehayes |
16'b1???_????_????_???? : alu_result = 16'h000f;
|
887 |
|
|
16'b01??_????_????_???? : alu_result = 16'h000e;
|
888 |
|
|
16'b001?_????_????_???? : alu_result = 16'h000d;
|
889 |
|
|
16'b0001_????_????_???? : alu_result = 16'h000c;
|
890 |
|
|
16'b0000_1???_????_???? : alu_result = 16'h000b;
|
891 |
|
|
16'b0000_01??_????_???? : alu_result = 16'h000a;
|
892 |
|
|
16'b0000_001?_????_???? : alu_result = 16'h0009;
|
893 |
|
|
16'b0000_0001_????_???? : alu_result = 16'h0008;
|
894 |
|
|
16'b0000_0000_1???_???? : alu_result = 16'h0007;
|
895 |
|
|
16'b0000_0000_01??_???? : alu_result = 16'h0006;
|
896 |
|
|
16'b0000_0000_001?_???? : alu_result = 16'h0005;
|
897 |
|
|
16'b0000_0000_0001_???? : alu_result = 16'h0004;
|
898 |
|
|
16'b0000_0000_0000_1??? : alu_result = 16'h0003;
|
899 |
|
|
16'b0000_0000_0000_01?? : alu_result = 16'h0002;
|
900 |
|
|
16'b0000_0000_0000_001? : alu_result = 16'h0001;
|
901 |
|
|
16'b0000_0000_0000_0001 : alu_result = 16'h0000;
|
902 |
|
|
endcase
|
903 |
|
|
next_zero = !(|alu_result);
|
904 |
|
|
next_negative = 1'b0;
|
905 |
|
|
next_carry = !(|rs1_data);
|
906 |
|
|
next_overflow = 1'b0;
|
907 |
|
|
end
|
908 |
|
|
|
909 |
|
|
// Instruction = ASR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 0 1
|
910 |
|
|
// ASR - Arithmetic Shift Right
|
911 |
|
|
// n = RS
|
912 |
|
|
// Cycles - P
|
913 |
|
|
{CONT, 16'b00001??????10001} :
|
914 |
|
|
begin
|
915 |
|
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
916 |
|
|
shift_filler = {16{rd_data[15]}};
|
917 |
12 |
rehayes |
|
918 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
919 |
|
|
ena_rd_high_byte = 1'b1;
|
920 |
|
|
alu_result = shift_out;
|
921 |
|
|
next_zero = !(|alu_result);
|
922 |
|
|
next_negative = alu_result[15];
|
923 |
|
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
924 |
|
|
next_overflow = rd_data[15] ^ alu_result[15]; // Table and text disagree
|
925 |
|
|
end
|
926 |
|
|
|
927 |
|
|
// Instruction = CSL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 1 0
|
928 |
|
|
// CSL - Logical Shift Left with Carry
|
929 |
|
|
// n = RS
|
930 |
|
|
// Cycles - P
|
931 |
|
|
{CONT, 16'b00001??????10010} :
|
932 |
|
|
begin
|
933 |
|
|
shift_left = 1'b1;
|
934 |
|
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
935 |
|
|
shift_filler = {16{carry_flag}};
|
936 |
|
|
|
937 |
|
|
ena_rd_low_byte = 1'b1;
|
938 |
|
|
ena_rd_high_byte = 1'b1;
|
939 |
|
|
alu_result = shift_out;
|
940 |
|
|
next_zero = !(|alu_result);
|
941 |
|
|
next_negative = alu_result[15];
|
942 |
|
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
943 |
|
|
next_overflow = rd_data[15] ^ alu_result[15];
|
944 |
|
|
end
|
945 |
|
|
|
946 |
|
|
// Instruction = CSR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 0 1 1
|
947 |
|
|
// Logical Shift Right with Carry
|
948 |
|
|
// n = RS
|
949 |
|
|
// Cycles - P
|
950 |
|
|
{CONT, 16'b00001??????10011} :
|
951 |
|
|
begin
|
952 |
|
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
953 |
|
|
shift_filler = {16{carry_flag}};
|
954 |
|
|
|
955 |
|
|
ena_rd_low_byte = 1'b1;
|
956 |
|
|
ena_rd_high_byte = 1'b1;
|
957 |
|
|
alu_result = shift_out;
|
958 |
|
|
next_zero = !(|alu_result);
|
959 |
|
|
next_negative = alu_result[15];
|
960 |
|
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
961 |
|
|
next_overflow = rd_data[15] ^ alu_result[15];
|
962 |
|
|
end
|
963 |
|
|
|
964 |
|
|
// Instruction = LSL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 0 0
|
965 |
|
|
// Logical Shift Left
|
966 |
|
|
// n = RS
|
967 |
|
|
// Cycles - P
|
968 |
|
|
{CONT, 16'b00001??????10100} :
|
969 |
|
|
begin
|
970 |
|
|
shift_left = 1'b1;
|
971 |
|
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
972 |
|
|
shift_filler = 16'h0000;
|
973 |
|
|
|
974 |
|
|
ena_rd_low_byte = 1'b1;
|
975 |
|
|
ena_rd_high_byte = 1'b1;
|
976 |
|
|
alu_result = shift_out;
|
977 |
|
|
next_zero = !(|alu_result);
|
978 |
|
|
next_negative = alu_result[15];
|
979 |
|
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
980 |
|
|
next_overflow = rd_data[15] ^ alu_result[15];
|
981 |
|
|
end
|
982 |
|
|
|
983 |
|
|
// Instruction = LSR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 0 1
|
984 |
|
|
// Logical Shift Right
|
985 |
|
|
// n = RS
|
986 |
|
|
// Cycles - P
|
987 |
|
|
{CONT, 16'b00001??????10101} :
|
988 |
|
|
begin
|
989 |
|
|
shift_ammount = {|rs1_data[15:4], rs1_data[3:0]};
|
990 |
|
|
shift_filler = 16'h0000;
|
991 |
|
|
|
992 |
|
|
ena_rd_low_byte = 1'b1;
|
993 |
|
|
ena_rd_high_byte = 1'b1;
|
994 |
|
|
alu_result = shift_out;
|
995 |
|
|
next_zero = !(|alu_result);
|
996 |
|
|
next_negative = alu_result[15];
|
997 |
|
|
next_carry = |rs1_data ? shift_rollover : carry_flag;
|
998 |
|
|
next_overflow = rd_data[15] ^ alu_result[15];
|
999 |
|
|
end
|
1000 |
|
|
|
1001 |
|
|
// Instruction = ROL RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 1 0
|
1002 |
|
|
// Rotate Left
|
1003 |
|
|
// n = RS
|
1004 |
|
|
// Cycles - P
|
1005 |
|
|
{CONT, 16'b00001??????10110} :
|
1006 |
|
|
begin
|
1007 |
|
|
shift_left = 1'b1;
|
1008 |
|
|
shift_ammount = {1'b0, rs1_data[3:0]};
|
1009 |
|
|
shift_filler = rd_data;
|
1010 |
|
|
|
1011 |
|
|
ena_rd_low_byte = 1'b1;
|
1012 |
|
|
ena_rd_high_byte = 1'b1;
|
1013 |
|
|
alu_result = shift_out;
|
1014 |
|
|
next_zero = !(|alu_result);
|
1015 |
|
|
next_negative = alu_result[15];
|
1016 |
|
|
next_overflow = 1'b0;
|
1017 |
|
|
end
|
1018 |
|
|
|
1019 |
|
|
// Instruction = ROR RD, RS, Op Code = 0 0 0 0 1 RD RS 1 0 1 1 1
|
1020 |
|
|
// Rotate Right
|
1021 |
|
|
// n = RS
|
1022 |
|
|
// Cycles - P
|
1023 |
|
|
{CONT, 16'b00001??????10111} :
|
1024 |
|
|
begin
|
1025 |
|
|
shift_ammount = {1'b0, rs1_data[3:0]};
|
1026 |
|
|
shift_filler = rd_data;
|
1027 |
|
|
|
1028 |
|
|
ena_rd_low_byte = 1'b1;
|
1029 |
|
|
ena_rd_high_byte = 1'b1;
|
1030 |
|
|
alu_result = shift_out;
|
1031 |
|
|
next_zero = !(|alu_result);
|
1032 |
|
|
next_negative = alu_result[15];
|
1033 |
|
|
next_overflow = 1'b0;
|
1034 |
|
|
end
|
1035 |
|
|
|
1036 |
|
|
// -----------------------------------------------------------------------
|
1037 |
|
|
// Instruction Group -- Shift instructions immediate
|
1038 |
|
|
// -----------------------------------------------------------------------
|
1039 |
|
|
|
1040 |
|
|
// Instruction = ASR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 0 1
|
1041 |
|
|
// ASR - Arithmetic Shift Right
|
1042 |
|
|
// n = IMM4
|
1043 |
|
|
// Cycles - P
|
1044 |
|
|
{CONT, 16'b00001???????1001} :
|
1045 |
|
|
begin
|
1046 |
|
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
1047 |
|
|
shift_filler = {16{rd_data[15]}};
|
1048 |
12 |
rehayes |
|
1049 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1050 |
|
|
ena_rd_high_byte = 1'b1;
|
1051 |
|
|
alu_result = shift_out;
|
1052 |
|
|
next_zero = !(|alu_result);
|
1053 |
|
|
next_negative = alu_result[15];
|
1054 |
|
|
next_carry = shift_rollover;
|
1055 |
|
|
next_overflow = rd_data[15] ^ alu_result[15]; // Table and text disagree
|
1056 |
|
|
end
|
1057 |
|
|
|
1058 |
|
|
// Instruction = CSL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 1 0
|
1059 |
|
|
// CSL - Logical Shift Left with Carry
|
1060 |
|
|
// n = IMM4
|
1061 |
|
|
// Cycles - P
|
1062 |
|
|
{CONT, 16'b00001???????1010} :
|
1063 |
|
|
begin
|
1064 |
|
|
shift_left = 1'b1;
|
1065 |
|
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
1066 |
|
|
shift_filler = {16{carry_flag}};
|
1067 |
12 |
rehayes |
|
1068 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1069 |
|
|
ena_rd_high_byte = 1'b1;
|
1070 |
|
|
alu_result = shift_out;
|
1071 |
|
|
next_zero = !(|alu_result);
|
1072 |
|
|
next_negative = alu_result[15];
|
1073 |
|
|
next_carry = shift_rollover;
|
1074 |
|
|
next_overflow = rd_data[15] ^ alu_result[15];
|
1075 |
|
|
end
|
1076 |
|
|
|
1077 |
|
|
// Instruction = CSR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 0 1 1
|
1078 |
|
|
// CSR - Logical Shift Right with Carry
|
1079 |
|
|
// n = IMM4
|
1080 |
|
|
// Cycles - P
|
1081 |
|
|
{CONT, 16'b00001???????1011} :
|
1082 |
|
|
begin
|
1083 |
|
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
1084 |
|
|
shift_filler = {16{carry_flag}};
|
1085 |
|
|
|
1086 |
|
|
ena_rd_low_byte = 1'b1;
|
1087 |
|
|
ena_rd_high_byte = 1'b1;
|
1088 |
|
|
alu_result = shift_out;
|
1089 |
|
|
next_zero = !(|alu_result);
|
1090 |
|
|
next_negative = alu_result[15];
|
1091 |
|
|
next_carry = shift_rollover;
|
1092 |
|
|
next_overflow = rd_data[15] ^ alu_result[15];
|
1093 |
|
|
end
|
1094 |
|
|
|
1095 |
|
|
// Instruction = LSL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 0 0
|
1096 |
|
|
// LSL - Logical Shift Left
|
1097 |
|
|
// n = IMM4
|
1098 |
|
|
// Cycles - P
|
1099 |
|
|
{CONT, 16'b00001???????1100} :
|
1100 |
|
|
begin
|
1101 |
|
|
shift_left = 1'b1;
|
1102 |
|
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
1103 |
|
|
shift_filler = 16'h0000;
|
1104 |
12 |
rehayes |
|
1105 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1106 |
|
|
ena_rd_high_byte = 1'b1;
|
1107 |
|
|
alu_result = shift_out;
|
1108 |
|
|
next_zero = !(|alu_result);
|
1109 |
|
|
next_negative = alu_result[15];
|
1110 |
|
|
next_carry = shift_rollover;
|
1111 |
|
|
next_overflow = rd_data[15] ^ alu_result[15];
|
1112 |
|
|
end
|
1113 |
|
|
|
1114 |
|
|
// Instruction = LSR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 0 1
|
1115 |
|
|
// LSR - Logical Shift Right
|
1116 |
|
|
// n = IMM4
|
1117 |
|
|
// Cycles - P
|
1118 |
|
|
{CONT, 16'b00001???????1101} :
|
1119 |
|
|
begin
|
1120 |
|
|
shift_ammount = {!(|op_code[7:4]), op_code[7:4]};
|
1121 |
|
|
shift_filler = 16'h0000;
|
1122 |
12 |
rehayes |
|
1123 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1124 |
|
|
ena_rd_high_byte = 1'b1;
|
1125 |
|
|
alu_result = shift_out;
|
1126 |
|
|
next_zero = !(|alu_result);
|
1127 |
|
|
next_negative = alu_result[15];
|
1128 |
|
|
next_carry = shift_rollover;
|
1129 |
|
|
next_overflow = rd_data[15] ^ alu_result[15];
|
1130 |
|
|
end
|
1131 |
|
|
|
1132 |
|
|
// Instruction = ROL RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 1 0
|
1133 |
|
|
// ROL - Rotate Left
|
1134 |
|
|
// n = IMM4
|
1135 |
|
|
// Cycles - P
|
1136 |
|
|
{CONT, 16'b00001???????1110} :
|
1137 |
|
|
begin
|
1138 |
|
|
shift_left = 1'b1;
|
1139 |
|
|
shift_ammount = {1'b0, op_code[7:4]};
|
1140 |
|
|
shift_filler = rd_data;
|
1141 |
12 |
rehayes |
|
1142 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1143 |
|
|
ena_rd_high_byte = 1'b1;
|
1144 |
|
|
alu_result = shift_out;
|
1145 |
|
|
next_zero = !(|alu_result);
|
1146 |
|
|
next_negative = alu_result[15];
|
1147 |
|
|
next_overflow = 1'b0;
|
1148 |
|
|
end
|
1149 |
|
|
|
1150 |
|
|
// Instruction = ROR RD, #IMM4, Op Code = 0 0 0 0 1 RD IMM4 1 1 1 1
|
1151 |
|
|
// ROR - Rotate Right
|
1152 |
|
|
// n = IMM4
|
1153 |
|
|
// Cycles - P
|
1154 |
|
|
{CONT, 16'b00001???????1111} :
|
1155 |
|
|
begin
|
1156 |
|
|
shift_ammount = {1'b0, op_code[7:4]};
|
1157 |
|
|
shift_filler = rd_data;
|
1158 |
12 |
rehayes |
|
1159 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1160 |
|
|
ena_rd_high_byte = 1'b1;
|
1161 |
|
|
alu_result = shift_out;
|
1162 |
|
|
next_zero = !(|alu_result);
|
1163 |
|
|
next_negative = alu_result[15];
|
1164 |
|
|
next_overflow = 1'b0;
|
1165 |
|
|
end
|
1166 |
|
|
|
1167 |
|
|
// -----------------------------------------------------------------------
|
1168 |
|
|
// Instruction Group -- Logical Triadic
|
1169 |
|
|
// -----------------------------------------------------------------------
|
1170 |
|
|
|
1171 |
|
|
// Instruction = AND RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 0 0
|
1172 |
|
|
// AND - Logical AND
|
1173 |
|
|
// RS1 & RS2 => RD
|
1174 |
|
|
// Cycles - P
|
1175 |
|
|
{CONT, 16'b00010?????????00} :
|
1176 |
|
|
begin
|
1177 |
|
|
ena_rd_low_byte = 1'b1;
|
1178 |
|
|
ena_rd_high_byte = 1'b1;
|
1179 |
|
|
|
1180 |
|
|
alu_result = rs1_data & rs2_data;
|
1181 |
|
|
next_zero = !(|alu_result);
|
1182 |
|
|
next_negative = alu_result[15];
|
1183 |
|
|
next_overflow = 1'b0;
|
1184 |
|
|
end
|
1185 |
|
|
|
1186 |
|
|
// Instruction = OR RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 1 0
|
1187 |
|
|
// OR - Logical OR
|
1188 |
|
|
// RS1 | RS2 => RD
|
1189 |
|
|
// Cycles - P
|
1190 |
|
|
{CONT, 16'b00010?????????10} :
|
1191 |
|
|
begin
|
1192 |
|
|
ena_rd_low_byte = 1'b1;
|
1193 |
|
|
ena_rd_high_byte = 1'b1;
|
1194 |
|
|
|
1195 |
|
|
alu_result = rs1_data | rs2_data;
|
1196 |
|
|
next_zero = !(|alu_result);
|
1197 |
|
|
next_negative = alu_result[15];
|
1198 |
|
|
next_overflow = 1'b0;
|
1199 |
|
|
end
|
1200 |
|
|
|
1201 |
|
|
// Instruction = XNOR RD, RS1, RS2, Op Code = 0 0 0 1 0 RD RS1 RS2 1 1
|
1202 |
|
|
// XNOR - Logical Exclusive NOR
|
1203 |
|
|
// ~(RS1 ^ RS2) => RD
|
1204 |
|
|
// Cycles - P
|
1205 |
|
|
{CONT, 16'b00010?????????11} :
|
1206 |
|
|
begin
|
1207 |
|
|
ena_rd_low_byte = 1'b1;
|
1208 |
|
|
ena_rd_high_byte = 1'b1;
|
1209 |
|
|
|
1210 |
|
|
alu_result = ~(rs1_data ^ rs2_data);
|
1211 |
|
|
next_zero = !(|alu_result);
|
1212 |
|
|
next_negative = alu_result[15];
|
1213 |
|
|
next_overflow = 1'b0;
|
1214 |
|
|
end
|
1215 |
|
|
|
1216 |
|
|
// -----------------------------------------------------------------------
|
1217 |
|
|
// Instruction Group -- Arithmetic Triadic
|
1218 |
|
|
// -----------------------------------------------------------------------
|
1219 |
|
|
|
1220 |
|
|
// Instruction = SUB RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 0 0
|
1221 |
|
|
// SUB - Subtract without Carry
|
1222 |
|
|
// RS1 - RS2 => RD
|
1223 |
|
|
// Cycles - P
|
1224 |
|
|
{CONT, 16'b00011?????????00} :
|
1225 |
|
|
begin
|
1226 |
|
|
ena_rd_low_byte = 1'b1;
|
1227 |
|
|
ena_rd_high_byte = 1'b1;
|
1228 |
|
|
|
1229 |
|
|
{next_carry, alu_result} = rs1_data - rs2_data;
|
1230 |
|
|
next_zero = !(|alu_result);
|
1231 |
|
|
next_negative = alu_result[15];
|
1232 |
|
|
next_overflow = (rs1_data[15] && !rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && rs2_data[15] && alu_result[15]);
|
1233 |
|
|
end
|
1234 |
|
|
|
1235 |
|
|
// Instruction = SBC RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 0 1
|
1236 |
|
|
// SBC - Subtract with Carry
|
1237 |
|
|
// RS1 - RS2 - C => RD
|
1238 |
|
|
// Cycles - P
|
1239 |
|
|
{CONT, 16'b00011?????????01} :
|
1240 |
|
|
begin
|
1241 |
|
|
ena_rd_low_byte = 1'b1;
|
1242 |
|
|
ena_rd_high_byte = 1'b1;
|
1243 |
|
|
|
1244 |
|
|
{next_carry, alu_result} = rs1_data - rs2_data - {15'b0, carry_flag};
|
1245 |
|
|
next_zero = !(|alu_result);
|
1246 |
|
|
next_negative = alu_result[15];
|
1247 |
|
|
next_overflow = (rs1_data[15] && !rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && rs2_data[15] && alu_result[15]);
|
1248 |
|
|
end
|
1249 |
|
|
|
1250 |
|
|
// Instruction = ADD RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 1 0
|
1251 |
|
|
// ADD - ADD without carry
|
1252 |
|
|
// RS1 + RS2 => RD
|
1253 |
|
|
// Cycles - P
|
1254 |
|
|
{CONT, 16'b00011?????????10} :
|
1255 |
|
|
begin
|
1256 |
|
|
ena_rd_low_byte = 1'b1;
|
1257 |
|
|
ena_rd_high_byte = 1'b1;
|
1258 |
|
|
|
1259 |
|
|
{next_carry, alu_result} = rs1_data + rs2_data;
|
1260 |
|
|
next_zero = !(|alu_result);
|
1261 |
|
|
next_negative = alu_result[15];
|
1262 |
|
|
next_overflow = (rs1_data[15] && rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && !rs2_data[15] && alu_result[15]);
|
1263 |
|
|
end
|
1264 |
|
|
|
1265 |
|
|
// Instruction = ADC RD, RS1, RS2, Op Code = 0 0 0 1 1 RD RS1 RS2 1 1
|
1266 |
|
|
// ADC - add with carry
|
1267 |
|
|
// RS1 + RS2 + C => RD
|
1268 |
|
|
// Cycles - P
|
1269 |
|
|
{CONT, 16'b00011?????????11} :
|
1270 |
|
|
begin
|
1271 |
|
|
ena_rd_low_byte = 1'b1;
|
1272 |
|
|
ena_rd_high_byte = 1'b1;
|
1273 |
|
|
|
1274 |
|
|
{next_carry, alu_result} = rs1_data + rs2_data + {15'b0, carry_flag};
|
1275 |
|
|
next_zero = !(|alu_result);
|
1276 |
|
|
next_negative = alu_result[15];
|
1277 |
|
|
next_overflow = (rs1_data[15] && rs2_data[15] && !alu_result[15]) || (!rs1_data[15] && !rs2_data[15] && alu_result[15]);
|
1278 |
|
|
end
|
1279 |
|
|
|
1280 |
|
|
// -----------------------------------------------------------------------
|
1281 |
|
|
// Instruction Group -- Branches
|
1282 |
|
|
// -----------------------------------------------------------------------
|
1283 |
|
|
|
1284 |
|
|
// Instruction = BCC REL9, Op Code = 0 0 1 0 0 0 0 REL9
|
1285 |
|
|
// Branch if Carry Cleared
|
1286 |
|
|
// If C = 0, then PC + $0002 + (REL9 << 1) => PC
|
1287 |
|
|
// Cycles - PP/P
|
1288 |
|
|
{CONT, 16'b0010000?????????} :
|
1289 |
|
|
begin
|
1290 |
|
|
if (!carry_flag)
|
1291 |
|
|
begin
|
1292 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1293 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1294 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1295 |
|
|
next_pc = pc_sum; // There is a race condition when the default declaration is used
|
1296 |
2 |
rehayes |
end
|
1297 |
|
|
end
|
1298 |
|
|
|
1299 |
|
|
// Instruction = BCS REL9, Op Code = 0 0 1 0 0 0 1 REL9
|
1300 |
|
|
// Branch if Carry Set
|
1301 |
|
|
// If C = 1, then PC + $0002 + (REL9 << 1) => PC
|
1302 |
|
|
// Cycles - PP/P
|
1303 |
|
|
{CONT, 16'b0010001?????????} :
|
1304 |
|
|
begin
|
1305 |
|
|
if (carry_flag)
|
1306 |
|
|
begin
|
1307 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1308 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1309 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1310 |
|
|
next_pc = pc_sum;
|
1311 |
2 |
rehayes |
end
|
1312 |
|
|
end
|
1313 |
|
|
|
1314 |
|
|
// Instruction = BNE REL9, Op Code = 0 0 1 0 0 1 0 REL9
|
1315 |
|
|
// Branch if Not Equal
|
1316 |
|
|
// If Z = 0, then PC + $0002 + (REL9 << 1) => PC
|
1317 |
|
|
// Cycles - PP/P
|
1318 |
|
|
{CONT, 16'b0010010?????????} :
|
1319 |
|
|
begin
|
1320 |
|
|
if (!zero_flag)
|
1321 |
|
|
begin
|
1322 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1323 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1324 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1325 |
|
|
next_pc = pc_sum;
|
1326 |
2 |
rehayes |
end
|
1327 |
|
|
end
|
1328 |
|
|
|
1329 |
|
|
// Instruction = BEQ REL9, Op Code = 0 0 1 0 0 1 1 REL9
|
1330 |
|
|
// Branch if Equal
|
1331 |
|
|
// If Z = 1, then PC + $0002 + (REL9 << 1) => PC
|
1332 |
|
|
// Cycles - PP/P
|
1333 |
|
|
{CONT, 16'b0010011?????????} :
|
1334 |
|
|
begin
|
1335 |
|
|
if (zero_flag)
|
1336 |
|
|
begin
|
1337 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1338 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1339 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1340 |
|
|
next_pc = pc_sum;
|
1341 |
2 |
rehayes |
end
|
1342 |
|
|
end
|
1343 |
|
|
|
1344 |
|
|
// Instruction = BPL REL9, Op Code = 0 0 1 0 1 0 0 REL9
|
1345 |
|
|
// Branch if Plus
|
1346 |
|
|
// If N = 0, then PC + $0002 + (REL9 << 1) => PC
|
1347 |
|
|
// Cycles - PP/P
|
1348 |
|
|
{CONT, 16'b0010100?????????} :
|
1349 |
|
|
begin
|
1350 |
|
|
if (!negative_flag)
|
1351 |
|
|
begin
|
1352 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1353 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1354 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1355 |
|
|
next_pc = pc_sum;
|
1356 |
2 |
rehayes |
end
|
1357 |
|
|
end
|
1358 |
|
|
|
1359 |
|
|
// Instruction = BMI REL9, Op Code = 0 0 1 0 1 0 1 REL9
|
1360 |
|
|
// Branch if Minus
|
1361 |
|
|
// If N = 1, then PC + $0002 + (REL9 << 1) => PC
|
1362 |
|
|
// Cycles - PP/P
|
1363 |
|
|
{CONT, 16'b0010101?????????} :
|
1364 |
|
|
begin
|
1365 |
|
|
if (negative_flag)
|
1366 |
|
|
begin
|
1367 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1368 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1369 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1370 |
|
|
next_pc = pc_sum;
|
1371 |
2 |
rehayes |
end
|
1372 |
|
|
end
|
1373 |
|
|
|
1374 |
|
|
// Instruction = BVC REL9, Op Code = 0 0 1 0 1 1 0 REL9
|
1375 |
|
|
// Branch if Overflow Cleared
|
1376 |
|
|
// If V = 0, then PC + $0002 + (REL9 << 1) => PC
|
1377 |
|
|
// Cycles - PP/P
|
1378 |
|
|
{CONT, 16'b0010110?????????} :
|
1379 |
|
|
begin
|
1380 |
|
|
if (!overflow_flag)
|
1381 |
|
|
begin
|
1382 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1383 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1384 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1385 |
|
|
next_pc = pc_sum;
|
1386 |
2 |
rehayes |
end
|
1387 |
|
|
end
|
1388 |
|
|
|
1389 |
|
|
// Instruction = BVS REL9, Op Code = 0 0 1 0 1 1 1 REL9
|
1390 |
|
|
// Branch if Overflow Set
|
1391 |
|
|
// If V = 1, then PC + $0002 + (REL9 << 1) => PC
|
1392 |
|
|
// Cycles - PP/P
|
1393 |
|
|
{CONT, 16'b0010111?????????} :
|
1394 |
|
|
begin
|
1395 |
|
|
if (overflow_flag)
|
1396 |
|
|
begin
|
1397 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1398 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1399 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1400 |
|
|
next_pc = pc_sum;
|
1401 |
2 |
rehayes |
end
|
1402 |
|
|
end
|
1403 |
|
|
|
1404 |
|
|
// Instruction = BHI REL9, Op Code = 0 0 1 1 0 0 0 REL9
|
1405 |
|
|
// Branch if Higher
|
1406 |
|
|
// If C | Z = 0, then PC + $0002 + (REL9 << 1) => PC
|
1407 |
|
|
// Cycles - PP/P
|
1408 |
|
|
{CONT, 16'b0011000?????????} :
|
1409 |
|
|
begin
|
1410 |
|
|
if (!(carry_flag || zero_flag))
|
1411 |
|
|
begin
|
1412 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1413 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1414 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1415 |
|
|
next_pc = pc_sum;
|
1416 |
2 |
rehayes |
end
|
1417 |
|
|
end
|
1418 |
|
|
|
1419 |
|
|
// Instruction = BLS REL9, Op Code = 0 0 1 1 0 0 1 REL9
|
1420 |
|
|
// Branch if Lower or Same
|
1421 |
|
|
// If C | Z = 1, then PC + $0002 + (REL9 << 1) => PC
|
1422 |
|
|
// Cycles - PP/P
|
1423 |
|
|
{CONT, 16'b0011001?????????} :
|
1424 |
|
|
begin
|
1425 |
|
|
if (carry_flag || zero_flag)
|
1426 |
|
|
begin
|
1427 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1428 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1429 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1430 |
|
|
next_pc = pc_sum;
|
1431 |
2 |
rehayes |
end
|
1432 |
|
|
end
|
1433 |
|
|
|
1434 |
|
|
// Instruction = BGE REL9, Op Code = 0 0 1 1 0 1 0 REL9
|
1435 |
|
|
// Branch if Greater than or Equal to Zero
|
1436 |
|
|
// If N ^ V = 0, then PC + $0002 + (REL9 << 1) => PC
|
1437 |
|
|
// Cycles - PP/P
|
1438 |
|
|
{CONT, 16'b0011010?????????} :
|
1439 |
|
|
begin
|
1440 |
|
|
if (!(negative_flag ^ overflow_flag))
|
1441 |
|
|
begin
|
1442 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1443 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1444 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1445 |
|
|
next_pc = pc_sum;
|
1446 |
2 |
rehayes |
end
|
1447 |
|
|
end
|
1448 |
|
|
|
1449 |
|
|
// Instruction = BLT REL9, Op Code = 0 0 1 1 0 1 1 REL9
|
1450 |
|
|
// Branch if Lower than Zero
|
1451 |
|
|
// If N ^ V = 1, then PC + $0002 + (REL9 << 1) => PC
|
1452 |
|
|
// Cycles - PP/P
|
1453 |
|
|
{CONT, 16'b0011011?????????} :
|
1454 |
|
|
begin
|
1455 |
|
|
if (negative_flag ^ overflow_flag)
|
1456 |
|
|
begin
|
1457 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1458 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1459 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1460 |
|
|
next_pc = pc_sum;
|
1461 |
2 |
rehayes |
end
|
1462 |
|
|
end
|
1463 |
|
|
|
1464 |
|
|
// Instruction = BGT REL9, Op Code = 0 0 1 1 1 0 0 REL9
|
1465 |
|
|
// Branch if Greater than Zero
|
1466 |
|
|
// If Z | (N ^ V) = 0, then PC + $0002 + (REL9 << 1) => PC
|
1467 |
|
|
// Cycles - PP/P
|
1468 |
|
|
{CONT, 16'b0011100?????????} :
|
1469 |
|
|
begin
|
1470 |
|
|
if (!(zero_flag || (negative_flag ^ overflow_flag)))
|
1471 |
|
|
begin
|
1472 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1473 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1474 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1475 |
|
|
next_pc = pc_sum;
|
1476 |
2 |
rehayes |
end
|
1477 |
|
|
end
|
1478 |
|
|
|
1479 |
|
|
// Instruction = BLE REL9, Op Code = 0 0 1 1 1 0 1 REL9
|
1480 |
|
|
// Branch if Less or Equal to Zero
|
1481 |
|
|
// If Z | (N ^ V) = 1, then PC + $0002 + (REL9 << 1) => PC
|
1482 |
|
|
// Cycles - PP/P
|
1483 |
|
|
{CONT, 16'b0011101?????????} :
|
1484 |
|
|
begin
|
1485 |
|
|
if (zero_flag || (negative_flag ^ overflow_flag))
|
1486 |
|
|
begin
|
1487 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1488 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1489 |
40 |
rehayes |
pc_incr_mux = jump_offset;
|
1490 |
|
|
next_pc = pc_sum;
|
1491 |
2 |
rehayes |
end
|
1492 |
|
|
end
|
1493 |
|
|
|
1494 |
|
|
// Instruction = BRA REL10, Op Code = 0 0 1 1 1 1 REL10
|
1495 |
|
|
// Branch Always, signed offset
|
1496 |
|
|
// PC + $0002 + (REL10 << 1) => PC
|
1497 |
|
|
// Cycles - PP
|
1498 |
|
|
{CONT, 16'b001111??????????} :
|
1499 |
|
|
begin
|
1500 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1501 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1502 |
40 |
rehayes |
pc_incr_mux = bra_offset;
|
1503 |
|
|
next_pc = pc_sum;
|
1504 |
2 |
rehayes |
end
|
1505 |
|
|
|
1506 |
|
|
|
1507 |
|
|
// -----------------------------------------------------------------------
|
1508 |
|
|
// Instruction Group -- Load and Store Instructions
|
1509 |
|
|
// -----------------------------------------------------------------------
|
1510 |
|
|
|
1511 |
|
|
// Instruction = LDB RD, (RB, #OFFS5), Op Code = 0 1 0 0 0 RD RB OFFS5
|
1512 |
|
|
// Load Byte from Memory, unsigned offset
|
1513 |
|
|
// M[RB, #OFFS5] => RD.L; $00 => RD.H
|
1514 |
|
|
// RB field == RS1 field
|
1515 |
|
|
// Cycles - Pr
|
1516 |
|
|
{CONT, 16'b01000???????????} :
|
1517 |
|
|
begin
|
1518 |
40 |
rehayes |
next_cpu_state = B_LOAD;
|
1519 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1520 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1521 |
|
|
next_pc = pc_sum;
|
1522 |
2 |
rehayes |
data_access = 1'b1;
|
1523 |
|
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
1524 |
|
|
end
|
1525 |
|
|
|
1526 |
|
|
// Instruction = LDW RD, (RB, #OFFS5), Op Code = 0 1 0 0 1 RD RB OFFS5
|
1527 |
|
|
// Load Word from Memory, unsigned offset
|
1528 |
|
|
// M[RB, #OFFS5] => RD
|
1529 |
|
|
// RB field == RS1 field
|
1530 |
|
|
// Cycles - PR
|
1531 |
|
|
{CONT, 16'b01001???????????} :
|
1532 |
|
|
begin
|
1533 |
40 |
rehayes |
next_cpu_state = W_LOAD;
|
1534 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1535 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1536 |
|
|
next_pc = pc_sum;
|
1537 |
2 |
rehayes |
data_access = 1'b1;
|
1538 |
|
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
1539 |
|
|
data_word_op = 1'b1;
|
1540 |
|
|
end
|
1541 |
|
|
|
1542 |
|
|
// Instruction = STB RS, (RB, #OFFS5), Op Code = 0 1 0 1 0 RS RB OFFS5
|
1543 |
|
|
// Store Byte to Memory, unsigned offset
|
1544 |
|
|
// RS.L => M[RB, #OFFS5]
|
1545 |
|
|
// RS field == RD fieild, RB field == RS1 field
|
1546 |
|
|
// Cycles - Pw
|
1547 |
|
|
{CONT, 16'b01010???????????} :
|
1548 |
|
|
begin
|
1549 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1550 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1551 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1552 |
|
|
next_pc = pc_sum;
|
1553 |
2 |
rehayes |
data_access = 1'b1;
|
1554 |
|
|
data_write = 1'b1;
|
1555 |
|
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
1556 |
|
|
end
|
1557 |
|
|
|
1558 |
|
|
// Instruction = STW RS, (RB, #OFFS5), Op Code = 0 1 0 1 1 RS RB OFFS5
|
1559 |
|
|
// Store Word to Memory, unsigned offset
|
1560 |
|
|
// RS => M[RB, #OFFS5]
|
1561 |
|
|
// RS field == RD fieild, RB field == RS1 field
|
1562 |
|
|
// Cycles - PW
|
1563 |
|
|
{CONT, 16'b01011???????????} :
|
1564 |
|
|
begin
|
1565 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1566 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1567 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1568 |
|
|
next_pc = pc_sum;
|
1569 |
2 |
rehayes |
data_access = 1'b1;
|
1570 |
|
|
data_write = 1'b1;
|
1571 |
|
|
data_address = rs1_data + {11'b0, op_code[4:0]};
|
1572 |
|
|
data_word_op = 1'b1;
|
1573 |
|
|
end
|
1574 |
|
|
|
1575 |
|
|
// Instruction = LDB RD, (RB, RI), Op Code = 0 1 1 0 0 RD RB RI 0 0
|
1576 |
|
|
// Load Byte from Memory
|
1577 |
|
|
// M[RB, RI] => RD.L; $00 => RD.H
|
1578 |
|
|
// RB field == RS1 field, RI field == RS2 field
|
1579 |
|
|
// Cycles - Pr
|
1580 |
|
|
{CONT, 16'b01100?????????00} :
|
1581 |
|
|
begin
|
1582 |
40 |
rehayes |
next_cpu_state = B_LOAD;
|
1583 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1584 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1585 |
|
|
next_pc = pc_sum;
|
1586 |
2 |
rehayes |
data_access = 1'b1;
|
1587 |
|
|
data_address = rs1_data + rs2_data;
|
1588 |
|
|
end
|
1589 |
|
|
|
1590 |
|
|
// Instruction = LDW RD, (RB, RI), Op Code = 0 1 1 0 1 RD RB RI 0 0
|
1591 |
|
|
// Load Word from Memory
|
1592 |
|
|
// M[RB, RI] => RD
|
1593 |
|
|
// RB field == RS1 field, RI field == RS2 field
|
1594 |
|
|
// Cycles - PR
|
1595 |
|
|
{CONT, 16'b01101?????????00} :
|
1596 |
|
|
begin
|
1597 |
40 |
rehayes |
next_cpu_state = W_LOAD;
|
1598 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1599 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1600 |
|
|
next_pc = pc_sum;
|
1601 |
2 |
rehayes |
data_access = 1'b1;
|
1602 |
|
|
data_address = rs1_data + rs2_data;
|
1603 |
|
|
data_word_op = 1'b1;
|
1604 |
|
|
end
|
1605 |
|
|
|
1606 |
|
|
// Instruction = STB RS, (RB, RI), Op Code = 0 1 1 1 0 RS RB RI 0 0
|
1607 |
|
|
// RS.L => M[RB, RI]
|
1608 |
|
|
// Store Byte to Memory
|
1609 |
|
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
1610 |
|
|
// Cycles - Pw
|
1611 |
|
|
{CONT, 16'b01110?????????00} :
|
1612 |
|
|
begin
|
1613 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1614 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1615 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1616 |
|
|
next_pc = pc_sum;
|
1617 |
2 |
rehayes |
data_access = 1'b1;
|
1618 |
|
|
data_write = 1'b1;
|
1619 |
|
|
data_address = rs1_data + rs2_data;
|
1620 |
|
|
end
|
1621 |
|
|
|
1622 |
|
|
// Instruction = STW RS, (RB, RI), Op Code = 0 1 1 1 1 RS RB RI 0 0
|
1623 |
|
|
// Store Word to Memory
|
1624 |
|
|
// RS => M[RB, RI]
|
1625 |
|
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
1626 |
|
|
// Cycles - PW
|
1627 |
|
|
{CONT, 16'b01111?????????00} :
|
1628 |
|
|
begin
|
1629 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1630 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1631 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1632 |
|
|
next_pc = pc_sum;
|
1633 |
2 |
rehayes |
data_access = 1'b1;
|
1634 |
|
|
data_write = 1'b1;
|
1635 |
|
|
data_address = rs1_data + rs2_data;
|
1636 |
|
|
data_word_op = 1'b1;
|
1637 |
|
|
end
|
1638 |
|
|
|
1639 |
|
|
// Instruction = LDB RD, (RB, RI+), Op Code = 0 1 1 0 0 RD RB RI 0 1
|
1640 |
|
|
// Load Byte from Memory
|
1641 |
|
|
// M[RB, RI] => RD.L; $00 => RD.H; RI+1 => RI
|
1642 |
|
|
// If the same general purpose register is used as index (RI) and destination register (RD),
|
1643 |
|
|
// the content of the register will not be incremented after the data move: M[RB, RI] => RD.L; $00 => RD.H
|
1644 |
|
|
// RB field == RS1 field, RI field == RS2 field
|
1645 |
|
|
// Cycles - Pr
|
1646 |
|
|
{CONT, 16'b01100?????????01} :
|
1647 |
|
|
begin
|
1648 |
40 |
rehayes |
next_cpu_state = B_LOAD;
|
1649 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1650 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1651 |
|
|
next_pc = pc_sum;
|
1652 |
2 |
rehayes |
data_access = 1'b1;
|
1653 |
|
|
data_address = rs1_data + rs2_data;
|
1654 |
|
|
alu_result = rs2_data + 16'h0001;
|
1655 |
12 |
rehayes |
sel_rd_field = 1'b0;
|
1656 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1657 |
|
|
ena_rd_high_byte = 1'b1;
|
1658 |
|
|
end
|
1659 |
|
|
|
1660 |
|
|
// Instruction = LDW RD, (RB, RI+), Op Code = 0 1 1 0 1 RD RB RI 0 1
|
1661 |
|
|
// Load Word from Memory
|
1662 |
|
|
// M[RB, RI] => RD; RI+2 => RI
|
1663 |
|
|
// If the same general purpose register is used as index (RI) and destination register (RD),
|
1664 |
|
|
// the content of the register will not be incremented after the data move: M[RB, RI] => RD
|
1665 |
|
|
// RB field == RS1 field, RI field == RS2 field
|
1666 |
|
|
// Cycles - PR
|
1667 |
|
|
{CONT, 16'b01101?????????01} :
|
1668 |
|
|
begin
|
1669 |
40 |
rehayes |
next_cpu_state = W_LOAD;
|
1670 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1671 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1672 |
|
|
next_pc = pc_sum;
|
1673 |
2 |
rehayes |
data_access = 1'b1;
|
1674 |
|
|
data_address = rs1_data + rs2_data;
|
1675 |
|
|
data_word_op = 1'b1;
|
1676 |
|
|
alu_result = rs2_data + 16'h0002;
|
1677 |
12 |
rehayes |
sel_rd_field = 1'b0;
|
1678 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1679 |
|
|
ena_rd_high_byte = 1'b1;
|
1680 |
|
|
end
|
1681 |
|
|
|
1682 |
|
|
// Instruction = STB RS, (RB, RI+), Op Code = 0 1 1 1 0 RS RB RI 0 1
|
1683 |
|
|
// Store Byte to Memory
|
1684 |
|
|
// RS.L => M[RB, RI]; RI+1 => RI
|
1685 |
|
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
1686 |
|
|
// Cycles - Pw
|
1687 |
|
|
{CONT, 16'b01110?????????01} :
|
1688 |
|
|
begin
|
1689 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1690 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1691 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1692 |
|
|
next_pc = pc_sum;
|
1693 |
2 |
rehayes |
data_access = 1'b1;
|
1694 |
|
|
data_write = 1'b1;
|
1695 |
|
|
data_address = rs1_data + rs2_data;
|
1696 |
|
|
alu_result = rs2_data + 16'h0001;
|
1697 |
12 |
rehayes |
sel_rd_field = 1'b0;
|
1698 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1699 |
|
|
ena_rd_high_byte = 1'b1;
|
1700 |
|
|
end
|
1701 |
|
|
|
1702 |
|
|
// Instruction = STW RS, (RB, RI+), Op Code = 0 1 1 1 1 RS RB RI 0 1
|
1703 |
|
|
// Store Word to Memory
|
1704 |
|
|
// RS => M[RB, RI]; RI+2 => RI
|
1705 |
|
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
1706 |
|
|
// Cycles - PW
|
1707 |
|
|
{CONT, 16'b01111?????????01} :
|
1708 |
|
|
begin
|
1709 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1710 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1711 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1712 |
|
|
next_pc = pc_sum;
|
1713 |
2 |
rehayes |
data_access = 1'b1;
|
1714 |
|
|
data_write = 1'b1;
|
1715 |
|
|
data_word_op = 1'b1;
|
1716 |
|
|
data_address = rs1_data + rs2_data;
|
1717 |
|
|
alu_result = rs2_data + 16'h0002;
|
1718 |
12 |
rehayes |
sel_rd_field = 1'b0;
|
1719 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1720 |
|
|
ena_rd_high_byte = 1'b1;
|
1721 |
|
|
end
|
1722 |
|
|
|
1723 |
|
|
// Instruction = LDB RD, (RB, -RI), Op Code = 0 1 1 0 0 RD RB RI 1 0
|
1724 |
|
|
// Load Byte from Memory
|
1725 |
|
|
// RI-1 => RI; M[RS, RI] => RD.L; $00 => RD.H
|
1726 |
|
|
// RB field == RS1 field, RI field == RS2 field
|
1727 |
|
|
// Cycles - Pr
|
1728 |
|
|
{CONT, 16'b01100?????????10} :
|
1729 |
|
|
begin
|
1730 |
40 |
rehayes |
next_cpu_state = B_LOAD;
|
1731 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1732 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1733 |
|
|
next_pc = pc_sum;
|
1734 |
2 |
rehayes |
data_access = 1'b1;
|
1735 |
|
|
alu_result = rs2_data + 16'hffff;
|
1736 |
|
|
data_address = rs1_data + alu_result;
|
1737 |
12 |
rehayes |
sel_rd_field = 1'b0;
|
1738 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1739 |
|
|
ena_rd_high_byte = 1'b1;
|
1740 |
|
|
end
|
1741 |
|
|
|
1742 |
|
|
// Instruction = LDW RD, (RB, -RI), Op Code = 0 1 1 0 1 RD RB RI 1 0
|
1743 |
|
|
// Load Word from Memory
|
1744 |
|
|
// RI-2 => RI; M[RS, RI] => RD
|
1745 |
|
|
// RB field == RS1 field, RI field == RS2 field
|
1746 |
|
|
// Cycles - PR
|
1747 |
|
|
{CONT, 16'b01101?????????10} :
|
1748 |
|
|
begin
|
1749 |
40 |
rehayes |
next_cpu_state = W_LOAD;
|
1750 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1751 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1752 |
|
|
next_pc = pc_sum;
|
1753 |
2 |
rehayes |
data_access = 1'b1;
|
1754 |
|
|
alu_result = rs2_data + 16'hfffe;
|
1755 |
|
|
data_address = rs1_data + alu_result;
|
1756 |
|
|
data_word_op = 1'b1;
|
1757 |
12 |
rehayes |
sel_rd_field = 1'b0;
|
1758 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1759 |
|
|
ena_rd_high_byte = 1'b1;
|
1760 |
|
|
end
|
1761 |
|
|
|
1762 |
|
|
// Instruction = STB RS, (RB, -RI), Op Code = 0 1 1 1 0 RS RB RI 1 0
|
1763 |
|
|
// Store Byte to Memory
|
1764 |
|
|
// RI-1 => RI; RS.L => M[RB, RI]
|
1765 |
|
|
// If the same general purpose register is used as index (RI) and source register (RS),
|
1766 |
|
|
// the unmodified content of the source register is written to the memory: RS.L => M[RB, RS-1]; RS-1 => RS
|
1767 |
|
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
1768 |
|
|
// Cycles - Pw
|
1769 |
|
|
{CONT, 16'b01110?????????10} :
|
1770 |
|
|
begin
|
1771 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1772 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1773 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1774 |
|
|
next_pc = pc_sum;
|
1775 |
2 |
rehayes |
data_access = 1'b1;
|
1776 |
|
|
data_write = 1'b1;
|
1777 |
|
|
alu_result = rs2_data + 16'hffff;
|
1778 |
|
|
data_address = rs1_data + alu_result;
|
1779 |
12 |
rehayes |
sel_rd_field = 1'b0;
|
1780 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1781 |
|
|
ena_rd_high_byte = 1'b1;
|
1782 |
|
|
end
|
1783 |
|
|
|
1784 |
|
|
// Instruction = STW RS, (RB, -RI), Op Code = 0 1 1 1 1 RS RB RI 1 0
|
1785 |
|
|
// Store Word to Memory
|
1786 |
|
|
// RI-2 => RI; RS => M[RB, RI]
|
1787 |
|
|
// If the same general purpose register is used as index (RI) and source register (RS),
|
1788 |
|
|
// the unmodified content of the source register is written to the memory: RS => M[RB, RS-2]; RS-2 => RS
|
1789 |
|
|
// RS field == RD fieild, RB field == RS1 field, RI field == RS2 field
|
1790 |
|
|
// Cycles - PW
|
1791 |
|
|
{CONT, 16'b01111?????????10} :
|
1792 |
|
|
begin
|
1793 |
5 |
rehayes |
next_cpu_state = S_STALL;
|
1794 |
2 |
rehayes |
load_next_inst = 1'b0;
|
1795 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
1796 |
|
|
next_pc = pc_sum;
|
1797 |
2 |
rehayes |
data_access = 1'b1;
|
1798 |
|
|
data_write = 1'b1;
|
1799 |
|
|
data_word_op = 1'b1;
|
1800 |
|
|
alu_result = rs2_data + 16'hfffe;
|
1801 |
|
|
data_address = rs1_data + alu_result;
|
1802 |
12 |
rehayes |
sel_rd_field = 1'b0;
|
1803 |
2 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1804 |
|
|
ena_rd_high_byte = 1'b1;
|
1805 |
|
|
end
|
1806 |
|
|
|
1807 |
|
|
// -----------------------------------------------------------------------
|
1808 |
|
|
// Instruction Group -- Bit Field Instructions
|
1809 |
|
|
// -----------------------------------------------------------------------
|
1810 |
|
|
|
1811 |
|
|
// Instruction = BFEXT RD, RS1, RS2, Op Code = 0 1 1 0 0 RD RS1 RS2 1 1
|
1812 |
|
|
// BFEXT - Bit Field Extract
|
1813 |
|
|
// RS1[(o+w):o] => RD[w:0]; 0 => RD[15:(w+1)]
|
1814 |
|
|
// Cycles - P
|
1815 |
|
|
{CONT, 16'b01100?????????11} :
|
1816 |
|
|
begin
|
1817 |
5 |
rehayes |
ena_rd_low_byte = 1'b1;
|
1818 |
2 |
rehayes |
ena_rd_high_byte = 1'b1;
|
1819 |
|
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
1820 |
|
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
1821 |
|
|
shift_in[bfi] = bf_mux_mask[bfi] ? rs1_data[bfi] : 1'b0;
|
1822 |
|
|
|
1823 |
|
|
alu_result = shift_out;
|
1824 |
|
|
next_zero = !(|alu_result);
|
1825 |
|
|
next_negative = alu_result[15];
|
1826 |
|
|
next_overflow = 1'b0;
|
1827 |
|
|
end
|
1828 |
|
|
|
1829 |
|
|
// Instruction = BFINS RD, RS1, RS2, Op Code = 0 1 1 0 1 RD RS1 RS2 1 1
|
1830 |
|
|
// BFINS - Bit Field Insert
|
1831 |
|
|
// RS1[w:0] => RD[(w+o):o
|
1832 |
|
|
// Cycles - P
|
1833 |
|
|
{CONT, 16'b01101?????????11} :
|
1834 |
|
|
begin
|
1835 |
|
|
ena_rd_low_byte = 1'b1;
|
1836 |
|
|
ena_rd_high_byte = 1'b1;
|
1837 |
|
|
shift_left = 1'b1;
|
1838 |
|
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
1839 |
|
|
shift_in = rs1_data;
|
1840 |
|
|
|
1841 |
|
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
1842 |
|
|
alu_result[bfi] = bf_mux_mask[bfi] ? shift_out[bfi] : rd_data[bfi];
|
1843 |
|
|
next_zero = !(|alu_result);
|
1844 |
|
|
next_negative = alu_result[15];
|
1845 |
|
|
next_overflow = 1'b0;
|
1846 |
|
|
end
|
1847 |
|
|
|
1848 |
|
|
// Instruction = BFINSI RD, RS1, RS2, Op Code = 0 1 1 1 0 RD RS1 RS2 1 1
|
1849 |
|
|
// BFINSI - Bit Field Insert and Invert
|
1850 |
|
|
// !RS1[w:0] => RD[w+o:o]
|
1851 |
|
|
// Cycles - P
|
1852 |
|
|
{CONT, 16'b01110?????????11} :
|
1853 |
|
|
begin
|
1854 |
|
|
ena_rd_low_byte = 1'b1;
|
1855 |
|
|
ena_rd_high_byte = 1'b1;
|
1856 |
|
|
shift_left = 1'b1;
|
1857 |
|
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
1858 |
|
|
shift_in = rs1_data;
|
1859 |
|
|
|
1860 |
|
|
for (bfi = 0; bfi <= 15; bfi = bfi + 1)
|
1861 |
|
|
alu_result[bfi] = bf_mux_mask[bfi] ? !shift_out[bfi] : rd_data[bfi];
|
1862 |
|
|
next_zero = !(|alu_result);
|
1863 |
|
|
next_negative = alu_result[15];
|
1864 |
|
|
next_overflow = 1'b0;
|
1865 |
|
|
end
|
1866 |
|
|
|
1867 |
|
|
// Instruction = BFINSX RD, RS1, RS2, Op Code = 0 1 1 1 1 RD RS1 RS2 1 1
|
1868 |
|
|
// BFINSX - Bit Field Insert and XNOR
|
1869 |
|
|
// !(RS1[w:0] ^ RD[w+o:o]) => RD[w+o:o]
|
1870 |
|
|
// Cycles - P
|
1871 |
|
|
{CONT, 16'b01111?????????11} :
|
1872 |
|
|
begin
|
1873 |
|
|
ena_rd_low_byte = 1'b1;
|
1874 |
|
|
ena_rd_high_byte = 1'b1;
|
1875 |
|
|
shift_left = 1'b1;
|
1876 |
|
|
shift_ammount = {1'b0, rs2_data[3:0]};
|
1877 |
|
|
shift_in = rs1_data;
|
1878 |
|
|
|
1879 |
26 |
rehayes |
for (bfii = 0; bfii <= 15; bfii = bfii + 1)
|
1880 |
|
|
alu_result[bfii] = bf_mux_mask[bfii] ? !(shift_out[bfii] ^ rd_data[bfii]) : rd_data[bfii];
|
1881 |
2 |
rehayes |
next_zero = !(|alu_result);
|
1882 |
|
|
next_negative = alu_result[15];
|
1883 |
|
|
next_overflow = 1'b0;
|
1884 |
|
|
end
|
1885 |
|
|
|
1886 |
|
|
// -----------------------------------------------------------------------
|
1887 |
|
|
// Instruction Group -- Logic Immediate Instructions
|
1888 |
|
|
// -----------------------------------------------------------------------
|
1889 |
|
|
|
1890 |
|
|
// Instruction = ANDL RD, #IMM8, Op Code = 1 0 0 0 0 RD IMM8
|
1891 |
|
|
// AND - Logical AND
|
1892 |
|
|
// RD.L & IMM8 => RD.L
|
1893 |
|
|
// Cycles - P
|
1894 |
|
|
{CONT, 16'b10000???????????} :
|
1895 |
|
|
begin
|
1896 |
|
|
ena_rd_low_byte = 1'b1;
|
1897 |
|
|
|
1898 |
|
|
alu_result = rd_data & {8'b0, op_code[7:0]};
|
1899 |
|
|
next_zero = !(|alu_result[7:0]);
|
1900 |
|
|
next_negative = alu_result[7];
|
1901 |
|
|
next_overflow = 1'b0;
|
1902 |
|
|
end
|
1903 |
|
|
|
1904 |
|
|
// Instruction = ANDH RD, #IMM8, Op Code = 1 0 0 0 1 RD IMM8
|
1905 |
|
|
// AND - Logical AND
|
1906 |
|
|
// RD.H & IMM8 => RD.H
|
1907 |
|
|
// Cycles - P
|
1908 |
|
|
{CONT, 16'b10001???????????} :
|
1909 |
|
|
begin
|
1910 |
|
|
ena_rd_high_byte = 1'b1;
|
1911 |
|
|
|
1912 |
|
|
alu_result = rd_data & {op_code[7:0], 8'b0};
|
1913 |
|
|
next_zero = !(|alu_result[15:8]);
|
1914 |
|
|
next_negative = alu_result[15];
|
1915 |
|
|
next_overflow = 1'b0;
|
1916 |
|
|
end
|
1917 |
|
|
|
1918 |
|
|
// Instruction = BITL RD, #IMM8, Op Code = 1 0 0 1 0 RD IMM8
|
1919 |
|
|
// RD.L & IMM8 => NONE
|
1920 |
|
|
{CONT, 16'b10010???????????} :
|
1921 |
|
|
begin
|
1922 |
|
|
|
1923 |
|
|
next_zero = !(|(rd_data[7:0] & op_code[7:0]));
|
1924 |
|
|
next_negative = rd_data[7] && op_code[7];
|
1925 |
|
|
next_overflow = 1'b0;
|
1926 |
|
|
end
|
1927 |
|
|
|
1928 |
|
|
// Instruction = BITH RD, #IMM8, Op Code = 1 0 0 1 1 RD IMM8
|
1929 |
|
|
// RD.H & IMM8 => NONE
|
1930 |
|
|
{CONT, 16'b10011???????????} :
|
1931 |
|
|
begin
|
1932 |
|
|
|
1933 |
|
|
next_zero = !(|(rd_data[15:8] & op_code[7:0]));
|
1934 |
|
|
next_negative = rd_data[15] && op_code[7];
|
1935 |
|
|
next_overflow = 1'b0;
|
1936 |
|
|
end
|
1937 |
|
|
|
1938 |
|
|
// Instruction = ORL RD, #IMM8, Op Code = 1 0 1 0 0 RD IMM8
|
1939 |
|
|
// OR - Logical OR
|
1940 |
|
|
// RD.L | IMM8 => RD.L
|
1941 |
|
|
{CONT, 16'b10100???????????} :
|
1942 |
|
|
begin
|
1943 |
|
|
ena_rd_low_byte = 1'b1;
|
1944 |
|
|
|
1945 |
|
|
alu_result = rd_data | {8'b0, op_code[7:0]};
|
1946 |
|
|
next_zero = !(|alu_result[7:0]);
|
1947 |
|
|
next_negative = alu_result[7];
|
1948 |
|
|
next_overflow = 1'b0;
|
1949 |
|
|
end
|
1950 |
|
|
|
1951 |
|
|
// Instruction = ORH RD, #IMM8, Op Code = 1 0 1 0 1 RD IMM8
|
1952 |
|
|
// OR - Logical OR
|
1953 |
|
|
// RD.H | IMM8 => RD.H
|
1954 |
|
|
{CONT, 16'b10101???????????} :
|
1955 |
|
|
begin
|
1956 |
|
|
ena_rd_high_byte = 1'b1;
|
1957 |
|
|
|
1958 |
|
|
alu_result = rd_data | {op_code[7:0], 8'b0};
|
1959 |
|
|
next_zero = !(|alu_result[15:8]);
|
1960 |
|
|
next_negative = alu_result[15];
|
1961 |
|
|
next_overflow = 1'b0;
|
1962 |
|
|
end
|
1963 |
|
|
|
1964 |
|
|
// Instruction = XNORL RD, #IMM8, Op Code = 1 0 1 1 0 RD IMM8
|
1965 |
|
|
// XNOR - Logical Exclusive NOR
|
1966 |
|
|
// ~(RD.L ^ IMM8) => RD.L
|
1967 |
|
|
{CONT, 16'b10110???????????} :
|
1968 |
|
|
begin
|
1969 |
|
|
ena_rd_low_byte = 1'b1;
|
1970 |
|
|
|
1971 |
|
|
alu_result = ~(rd_data ^ {8'b0, op_code[7:0]});
|
1972 |
|
|
next_zero = !(|alu_result[7:0]);
|
1973 |
|
|
next_negative = alu_result[7];
|
1974 |
|
|
next_overflow = 1'b0;
|
1975 |
|
|
end
|
1976 |
|
|
|
1977 |
|
|
// Instruction = XNORH RD, #IMM8, Op Code = 1 0 1 1 1 RD IMM8
|
1978 |
|
|
// XNOR - Logical Exclusive NOR
|
1979 |
|
|
// ~(RD.H ^ IMM8) => RD.H
|
1980 |
|
|
{CONT, 16'b10111???????????} :
|
1981 |
|
|
begin
|
1982 |
|
|
ena_rd_high_byte = 1'b1;
|
1983 |
|
|
|
1984 |
|
|
alu_result = ~(rd_data ^ {op_code[7:0], 8'b0});
|
1985 |
|
|
next_zero = !(|alu_result[15:8]);
|
1986 |
|
|
next_negative = alu_result[15];
|
1987 |
|
|
next_overflow = 1'b0;
|
1988 |
|
|
end
|
1989 |
|
|
|
1990 |
|
|
// -----------------------------------------------------------------------
|
1991 |
|
|
// Instruction Group -- Arithmetic Immediate Instructions
|
1992 |
|
|
// -----------------------------------------------------------------------
|
1993 |
|
|
|
1994 |
|
|
// Instruction = SUBL RD, #IMM8, Op Code = 1 1 0 0 0 RD IMM8
|
1995 |
|
|
// SUB - Subtract without Carry
|
1996 |
|
|
// RD - $00:IMM8 => RD
|
1997 |
|
|
// Cycles - P
|
1998 |
|
|
{CONT, 16'b11000???????????} :
|
1999 |
|
|
begin
|
2000 |
|
|
ena_rd_low_byte = 1'b1;
|
2001 |
|
|
ena_rd_high_byte = 1'b1;
|
2002 |
|
|
|
2003 |
|
|
alu_result = rd_data - {8'b0, op_code[7:0]};
|
2004 |
|
|
next_zero = !(|alu_result);
|
2005 |
|
|
next_negative = alu_result[15];
|
2006 |
|
|
next_carry = (!rd_data[7] && op_code[7]) || (!rd_data[7] && alu_result[7]) || (op_code[7] && alu_result[7]);
|
2007 |
|
|
next_overflow = (rd_data[7] && !op_code[7] && !alu_result[7]) || (!rd_data[7] && op_code[7] && alu_result[7]);
|
2008 |
|
|
end
|
2009 |
|
|
|
2010 |
|
|
// Instruction = SUBH RD, #IMM8, Op Code = 1 1 0 0 1 RD IMM8
|
2011 |
|
|
// SUB - Subtract without Carry
|
2012 |
|
|
// RD - IMM8:$00 => RD
|
2013 |
|
|
// Cycles - P
|
2014 |
|
|
{CONT, 16'b11001???????????} :
|
2015 |
|
|
begin
|
2016 |
|
|
ena_rd_low_byte = 1'b1;
|
2017 |
|
|
ena_rd_high_byte = 1'b1;
|
2018 |
|
|
|
2019 |
|
|
{next_carry, alu_result} = rd_data - {op_code[7:0], 8'b0};
|
2020 |
|
|
next_zero = !(|alu_result);
|
2021 |
|
|
next_negative = alu_result[15];
|
2022 |
|
|
next_overflow = (rd_data[15] && !op_code[7] && !alu_result[15]) || (!rd_data[15] && op_code[7] && alu_result[15]);
|
2023 |
|
|
end
|
2024 |
|
|
|
2025 |
|
|
// Instruction = CMPL RS, #IMM8, Op Code = 1 1 0 1 0 RS IMM8
|
2026 |
|
|
// RS.L - IMM8 => NONE, only condition code flags get updated
|
2027 |
|
|
// RS field == RD field
|
2028 |
|
|
// Cycles - P
|
2029 |
|
|
{CONT, 16'b11010???????????} :
|
2030 |
|
|
begin
|
2031 |
|
|
|
2032 |
|
|
alu_result = {8'b0, rd_data[7:0] - op_code[7:0]};
|
2033 |
|
|
next_zero = !(|alu_result[7:0]);
|
2034 |
|
|
next_negative = alu_result[7];
|
2035 |
|
|
next_carry = (!rd_data[7] && op_code[7]) || (!rd_data[7] && alu_result[7]) || (op_code[7] && alu_result[7]);
|
2036 |
|
|
next_overflow = (rd_data[7] && !op_code[7] && !alu_result[7]) || (!rd_data[7] && op_code[7] && alu_result[7]);
|
2037 |
|
|
end
|
2038 |
|
|
|
2039 |
|
|
// Instruction = CPCH RS, #IMM8, Op Code = 1 1 0 1 1 RS IMM8
|
2040 |
|
|
// RS.H - IMM8 - C => NONE, only condition code flags get updated
|
2041 |
|
|
// RS field == RD field
|
2042 |
|
|
// Cycles - P
|
2043 |
|
|
{CONT, 16'b11011???????????} :
|
2044 |
|
|
begin
|
2045 |
|
|
|
2046 |
|
|
alu_result = {rd_data[15:8], 8'b0} - {op_code[7:0], 8'b0} - {7'b0, carry_flag, 8'b0};
|
2047 |
|
|
next_zero = !(|alu_result[15:8]) && zero_flag;
|
2048 |
|
|
next_negative = alu_result[15];
|
2049 |
|
|
next_carry = (!rd_data[15] && op_code[7]) || (!rd_data[15] && alu_result[15]) || (op_code[7] && alu_result[15]);
|
2050 |
|
|
next_overflow = (rd_data[15] && !op_code[7] && !alu_result[15]) || (!rd_data[15] && op_code[7] && alu_result[15]);
|
2051 |
|
|
end
|
2052 |
|
|
|
2053 |
|
|
// Instruction = ADDL RD, #IMM8, Op Code = 1 1 1 0 0 RD IMM8
|
2054 |
|
|
// ADD - ADD without carry
|
2055 |
|
|
// RD + $00:IMM8 => RD
|
2056 |
|
|
// Cycles - P
|
2057 |
|
|
{CONT, 16'b11100???????????} :
|
2058 |
|
|
begin
|
2059 |
|
|
ena_rd_low_byte = 1'b1;
|
2060 |
|
|
ena_rd_high_byte = 1'b1;
|
2061 |
|
|
|
2062 |
|
|
alu_result = rd_data + {8'b0, op_code[7:0]};
|
2063 |
|
|
next_zero = !(|alu_result);
|
2064 |
|
|
next_negative = alu_result[15];
|
2065 |
|
|
next_carry = (rd_data[7] && op_code[7]) || (rd_data[7] && !alu_result[7]) || (op_code[7] && !alu_result[7]);
|
2066 |
|
|
next_overflow = (!rd_data[7] && !op_code[7] && alu_result[7]) || (rd_data[7] && op_code[7] && !alu_result[7]);
|
2067 |
|
|
end
|
2068 |
|
|
|
2069 |
|
|
// Instruction = ADDH RD, #IMM8, Op Code = 1 1 1 0 1 RD IMM8
|
2070 |
|
|
// ADD - ADD without carry
|
2071 |
|
|
// RD + IMM8:$00 => RD
|
2072 |
|
|
// Cycles - P
|
2073 |
|
|
{CONT, 16'b11101???????????} :
|
2074 |
|
|
begin
|
2075 |
|
|
ena_rd_low_byte = 1'b1;
|
2076 |
|
|
ena_rd_high_byte = 1'b1;
|
2077 |
|
|
|
2078 |
|
|
{next_carry, alu_result} = rd_data + {op_code[7:0], 8'b0};
|
2079 |
|
|
next_zero = !(|alu_result);
|
2080 |
|
|
next_negative = alu_result[15];
|
2081 |
|
|
next_overflow = (rd_data[15] && op_code[7] && !alu_result[15]) || (!rd_data[15] && !op_code[7] && alu_result[15]);
|
2082 |
|
|
end
|
2083 |
|
|
|
2084 |
|
|
// Instruction = LDL RD, #IMM8, Op Code = 1 1 1 1 0 RD IMM8
|
2085 |
|
|
// IMM8 => RD.L; $00 => RD.H, High Byte is cleared
|
2086 |
|
|
// Cycles - P
|
2087 |
|
|
{CONT, 16'b11110???????????} :
|
2088 |
|
|
begin
|
2089 |
|
|
ena_rd_low_byte = 1'b1;
|
2090 |
|
|
ena_rd_high_byte = 1'b1;
|
2091 |
|
|
|
2092 |
|
|
alu_result = {8'b0, op_code[7:0]};
|
2093 |
|
|
end
|
2094 |
|
|
|
2095 |
|
|
// Instruction = LDH RD, #IMM8, Op Code = 1 1 1 1 1 RD IMM8
|
2096 |
|
|
// IMM8 => RD.H, Low Byte is unchanged
|
2097 |
|
|
// Cycles - P
|
2098 |
|
|
{CONT, 16'b11111???????????} :
|
2099 |
|
|
begin
|
2100 |
|
|
ena_rd_high_byte = 1'b1;
|
2101 |
|
|
|
2102 |
|
|
alu_result = {op_code[7:0], 8'b0};
|
2103 |
|
|
end
|
2104 |
|
|
default :
|
2105 |
|
|
begin
|
2106 |
26 |
rehayes |
// synopsys translate_off
|
2107 |
2 |
rehayes |
$display("\nOP Code Error\n");
|
2108 |
26 |
rehayes |
// synopsys translate_on
|
2109 |
12 |
rehayes |
next_cpu_state = DEBUG;
|
2110 |
40 |
rehayes |
pc_incr_mux = 16'h0000;
|
2111 |
|
|
next_pc = pc_sum;
|
2112 |
12 |
rehayes |
load_next_inst = 1'b0;
|
2113 |
17 |
rehayes |
op_code_error = 1'b1;
|
2114 |
2 |
rehayes |
end
|
2115 |
|
|
endcase
|
2116 |
40 |
rehayes |
|
2117 |
2 |
rehayes |
end // always
|
2118 |
|
|
|
2119 |
|
|
xgate_barrel_shift barrel_shift(
|
2120 |
|
|
// outputs
|
2121 |
|
|
.shift_out( shift_out ),
|
2122 |
|
|
.shift_rollover( shift_rollover ),
|
2123 |
|
|
// inputs
|
2124 |
|
|
.shift_left( shift_left ),
|
2125 |
|
|
.shift_ammount( shift_ammount ),
|
2126 |
|
|
.shift_in( shift_in ),
|
2127 |
|
|
.shift_filler( shift_filler )
|
2128 |
|
|
);
|
2129 |
|
|
|
2130 |
|
|
// Three to Eight line decoder
|
2131 |
|
|
always @*
|
2132 |
26 |
rehayes |
case (semaph_risc) // synopsys parallel_case
|
2133 |
2 |
rehayes |
4'h0 : semap_risc_bit = 8'b0000_0001;
|
2134 |
|
|
4'h1 : semap_risc_bit = 8'b0000_0010;
|
2135 |
|
|
4'h2 : semap_risc_bit = 8'b0000_0100;
|
2136 |
|
|
4'h3 : semap_risc_bit = 8'b0000_1000;
|
2137 |
|
|
4'h4 : semap_risc_bit = 8'b0001_0000;
|
2138 |
|
|
4'h5 : semap_risc_bit = 8'b0010_0000;
|
2139 |
|
|
4'h6 : semap_risc_bit = 8'b0100_0000;
|
2140 |
|
|
4'h7 : semap_risc_bit = 8'b1000_0000;
|
2141 |
|
|
endcase
|
2142 |
12 |
rehayes |
|
2143 |
2 |
rehayes |
assign semaph_stat = |risc_semap;
|
2144 |
|
|
|
2145 |
5 |
rehayes |
// A "generate" statment would be good here but it's not supported in iverilog
|
2146 |
2 |
rehayes |
// Semaphore Bit
|
2147 |
|
|
semaphore_bit semaphore_0(
|
2148 |
|
|
// outputs
|
2149 |
|
|
.host_status( host_semap[0] ),
|
2150 |
|
|
.risc_status( risc_semap[0] ),
|
2151 |
|
|
// inputs
|
2152 |
|
|
.risc_clk( risc_clk ),
|
2153 |
|
|
.async_rst_b( async_rst_b ),
|
2154 |
|
|
.risc_bit_sel( semap_risc_bit[0] ),
|
2155 |
|
|
.csem( clear_semaph ),
|
2156 |
|
|
.ssem( set_semaph ),
|
2157 |
|
|
.host_wrt( write_xgsem ),
|
2158 |
|
|
.host_bit_mask( perif_data[8] ),
|
2159 |
|
|
.host_bit( perif_data[0] )
|
2160 |
|
|
);
|
2161 |
|
|
|
2162 |
|
|
// Semaphore Bit
|
2163 |
|
|
semaphore_bit semaphore_1(
|
2164 |
|
|
// outputs
|
2165 |
|
|
.host_status( host_semap[1] ),
|
2166 |
|
|
.risc_status( risc_semap[1] ),
|
2167 |
|
|
// inputs
|
2168 |
|
|
.risc_clk( risc_clk ),
|
2169 |
|
|
.async_rst_b( async_rst_b ),
|
2170 |
|
|
.risc_bit_sel( semap_risc_bit[1] ),
|
2171 |
|
|
.csem( clear_semaph ),
|
2172 |
|
|
.ssem( set_semaph ),
|
2173 |
|
|
.host_wrt( write_xgsem ),
|
2174 |
|
|
.host_bit_mask( perif_data[9] ),
|
2175 |
|
|
.host_bit( perif_data[1] )
|
2176 |
|
|
);
|
2177 |
|
|
|
2178 |
|
|
// Semaphore Bit
|
2179 |
|
|
semaphore_bit semaphore_2(
|
2180 |
|
|
// outputs
|
2181 |
|
|
.host_status( host_semap[2] ),
|
2182 |
|
|
.risc_status( risc_semap[2] ),
|
2183 |
|
|
// inputs
|
2184 |
|
|
.risc_clk( risc_clk ),
|
2185 |
|
|
.async_rst_b( async_rst_b ),
|
2186 |
|
|
.risc_bit_sel( semap_risc_bit[2] ),
|
2187 |
|
|
.csem( clear_semaph ),
|
2188 |
|
|
.ssem( set_semaph ),
|
2189 |
|
|
.host_wrt( write_xgsem ),
|
2190 |
|
|
.host_bit_mask( perif_data[10] ),
|
2191 |
|
|
.host_bit( perif_data[2] )
|
2192 |
|
|
);
|
2193 |
|
|
|
2194 |
|
|
// Semaphore Bit
|
2195 |
|
|
semaphore_bit semaphore_3(
|
2196 |
|
|
// outputs
|
2197 |
|
|
.host_status( host_semap[3] ),
|
2198 |
|
|
.risc_status( risc_semap[3] ),
|
2199 |
|
|
// inputs
|
2200 |
|
|
.risc_clk( risc_clk ),
|
2201 |
|
|
.async_rst_b( async_rst_b ),
|
2202 |
|
|
.risc_bit_sel( semap_risc_bit[3] ),
|
2203 |
|
|
.csem( clear_semaph ),
|
2204 |
|
|
.ssem( set_semaph ),
|
2205 |
|
|
.host_wrt( write_xgsem ),
|
2206 |
|
|
.host_bit_mask( perif_data[11] ),
|
2207 |
|
|
.host_bit( perif_data[2] )
|
2208 |
|
|
);
|
2209 |
|
|
|
2210 |
|
|
// Semaphore Bit
|
2211 |
|
|
semaphore_bit semaphore_4(
|
2212 |
|
|
// outputs
|
2213 |
|
|
.host_status( host_semap[4] ),
|
2214 |
|
|
.risc_status( risc_semap[4] ),
|
2215 |
|
|
// inputs
|
2216 |
|
|
.risc_clk( risc_clk ),
|
2217 |
|
|
.async_rst_b( async_rst_b ),
|
2218 |
|
|
.risc_bit_sel( semap_risc_bit[4] ),
|
2219 |
|
|
.csem( clear_semaph ),
|
2220 |
|
|
.ssem( set_semaph ),
|
2221 |
|
|
.host_wrt( write_xgsem ),
|
2222 |
|
|
.host_bit_mask( perif_data[12] ),
|
2223 |
|
|
.host_bit( perif_data[4] )
|
2224 |
|
|
);
|
2225 |
|
|
|
2226 |
|
|
// Semaphore Bit
|
2227 |
|
|
semaphore_bit semaphore_5(
|
2228 |
|
|
// outputs
|
2229 |
|
|
.host_status( host_semap[5] ),
|
2230 |
|
|
.risc_status( risc_semap[5] ),
|
2231 |
|
|
// inputs
|
2232 |
|
|
.risc_clk( risc_clk ),
|
2233 |
|
|
.async_rst_b( async_rst_b ),
|
2234 |
|
|
.risc_bit_sel( semap_risc_bit[5] ),
|
2235 |
|
|
.csem( clear_semaph ),
|
2236 |
|
|
.ssem( set_semaph ),
|
2237 |
|
|
.host_wrt( write_xgsem ),
|
2238 |
|
|
.host_bit_mask( perif_data[13] ),
|
2239 |
|
|
.host_bit( perif_data[5] )
|
2240 |
|
|
);
|
2241 |
|
|
|
2242 |
|
|
// Semaphore Bit
|
2243 |
|
|
semaphore_bit semaphore_6(
|
2244 |
|
|
// outputs
|
2245 |
|
|
.host_status( host_semap[6] ),
|
2246 |
|
|
.risc_status( risc_semap[6] ),
|
2247 |
|
|
// inputs
|
2248 |
|
|
.risc_clk( risc_clk ),
|
2249 |
|
|
.async_rst_b( async_rst_b ),
|
2250 |
|
|
.risc_bit_sel( semap_risc_bit[6] ),
|
2251 |
|
|
.csem( clear_semaph ),
|
2252 |
|
|
.ssem( set_semaph ),
|
2253 |
|
|
.host_wrt( write_xgsem ),
|
2254 |
|
|
.host_bit_mask( perif_data[14] ),
|
2255 |
|
|
.host_bit( perif_data[6] )
|
2256 |
|
|
);
|
2257 |
|
|
|
2258 |
|
|
// Semaphore Bit
|
2259 |
|
|
semaphore_bit semaphore_7(
|
2260 |
|
|
// outputs
|
2261 |
|
|
.host_status( host_semap[7] ),
|
2262 |
|
|
.risc_status( risc_semap[7] ),
|
2263 |
|
|
// inputs
|
2264 |
|
|
.risc_clk( risc_clk ),
|
2265 |
|
|
.async_rst_b( async_rst_b ),
|
2266 |
|
|
.risc_bit_sel( semap_risc_bit[7] ),
|
2267 |
|
|
.csem( clear_semaph ),
|
2268 |
|
|
.ssem( set_semaph ),
|
2269 |
|
|
.host_wrt( write_xgsem ),
|
2270 |
|
|
.host_bit_mask( perif_data[15] ),
|
2271 |
|
|
.host_bit( perif_data[7] )
|
2272 |
|
|
);
|
2273 |
|
|
|
2274 |
|
|
|
2275 |
|
|
endmodule // xgate_inst_decode
|
2276 |
|
|
|
2277 |
|
|
// -----------------------------------------------------------------------------
|
2278 |
|
|
// -----------------------------------------------------------------------------
|
2279 |
|
|
// -----------------------------------------------------------------------------
|
2280 |
|
|
|
2281 |
|
|
module xgate_barrel_shift (
|
2282 |
|
|
output reg [15:0] shift_out,
|
2283 |
|
|
output reg shift_rollover,
|
2284 |
|
|
|
2285 |
|
|
input shift_left,
|
2286 |
|
|
input [ 4:0] shift_ammount,
|
2287 |
|
|
input [15:0] shift_in,
|
2288 |
|
|
input [15:0] shift_filler
|
2289 |
|
|
);
|
2290 |
|
|
|
2291 |
|
|
always @*
|
2292 |
26 |
rehayes |
casez ({shift_left, shift_ammount}) // synopsys parallel_case
|
2293 |
2 |
rehayes |
// Start Right Shifts
|
2294 |
|
|
6'b0_0_0000 :
|
2295 |
|
|
begin
|
2296 |
|
|
shift_out = shift_in;
|
2297 |
|
|
shift_rollover = 1'b0;
|
2298 |
|
|
end
|
2299 |
|
|
6'b0_0_0001 :
|
2300 |
|
|
begin
|
2301 |
|
|
shift_out = {shift_filler[ 0], shift_in[15: 1]};
|
2302 |
|
|
shift_rollover = shift_in[ 0];
|
2303 |
|
|
end
|
2304 |
|
|
6'b0_0_0010 :
|
2305 |
|
|
begin
|
2306 |
|
|
shift_out = {shift_filler[ 1:0], shift_in[15: 2]};
|
2307 |
|
|
shift_rollover = shift_in[ 1];
|
2308 |
|
|
end
|
2309 |
|
|
6'b0_0_0011 :
|
2310 |
|
|
begin
|
2311 |
|
|
shift_out = {shift_filler[ 2:0], shift_in[15: 3]};
|
2312 |
|
|
shift_rollover = shift_in[ 2];
|
2313 |
|
|
end
|
2314 |
|
|
6'b0_0_0100 :
|
2315 |
|
|
begin
|
2316 |
|
|
shift_out = {shift_filler[ 3:0], shift_in[15: 4]};
|
2317 |
|
|
shift_rollover = shift_in[ 3];
|
2318 |
|
|
end
|
2319 |
|
|
6'b0_0_0101 :
|
2320 |
|
|
begin
|
2321 |
|
|
shift_out = {shift_filler[ 4:0], shift_in[15: 5]};
|
2322 |
|
|
shift_rollover = shift_in[ 4];
|
2323 |
|
|
end
|
2324 |
|
|
6'b0_0_0110 :
|
2325 |
|
|
begin
|
2326 |
|
|
shift_out = {shift_filler[ 5:0], shift_in[15: 6]};
|
2327 |
|
|
shift_rollover = shift_in[ 5];
|
2328 |
|
|
end
|
2329 |
|
|
6'b0_0_0111 :
|
2330 |
|
|
begin
|
2331 |
|
|
shift_out = {shift_filler[ 6:0], shift_in[15: 7]};
|
2332 |
|
|
shift_rollover = shift_in[ 6];
|
2333 |
|
|
end
|
2334 |
|
|
6'b0_0_1000 :
|
2335 |
|
|
begin
|
2336 |
|
|
shift_out = {shift_filler[ 7:0], shift_in[15: 8]};
|
2337 |
|
|
shift_rollover = shift_in[ 7];
|
2338 |
|
|
end
|
2339 |
|
|
6'b0_0_1001 :
|
2340 |
|
|
begin
|
2341 |
|
|
shift_out = {shift_filler[ 8:0], shift_in[15: 9]};
|
2342 |
|
|
shift_rollover = shift_in[ 8];
|
2343 |
|
|
end
|
2344 |
|
|
6'b0_0_1010 :
|
2345 |
|
|
begin
|
2346 |
|
|
shift_out = {shift_filler[ 9:0], shift_in[15:10]};
|
2347 |
|
|
shift_rollover = shift_in[ 9];
|
2348 |
|
|
end
|
2349 |
|
|
6'b0_0_1011 :
|
2350 |
|
|
begin
|
2351 |
|
|
shift_out = {shift_filler[10:0], shift_in[15:11]};
|
2352 |
|
|
shift_rollover = shift_in[10];
|
2353 |
|
|
end
|
2354 |
|
|
6'b0_0_1100 :
|
2355 |
|
|
begin
|
2356 |
|
|
shift_out = {shift_filler[11:0], shift_in[15:12]};
|
2357 |
|
|
shift_rollover = shift_in[11];
|
2358 |
|
|
end
|
2359 |
|
|
6'b0_0_1101 :
|
2360 |
|
|
begin
|
2361 |
|
|
shift_out = {shift_filler[12:0], shift_in[15:13]};
|
2362 |
|
|
shift_rollover = shift_in[12];
|
2363 |
|
|
end
|
2364 |
|
|
6'b0_0_1110 :
|
2365 |
|
|
begin
|
2366 |
|
|
shift_out = {shift_filler[13:0], shift_in[15:14]};
|
2367 |
|
|
shift_rollover = shift_in[13];
|
2368 |
|
|
end
|
2369 |
|
|
6'b0_0_1111 :
|
2370 |
|
|
begin
|
2371 |
|
|
shift_out = {shift_filler[14:0], shift_in[15]};
|
2372 |
|
|
shift_rollover = shift_in[14];
|
2373 |
|
|
end
|
2374 |
|
|
6'b0_1_???? :
|
2375 |
|
|
begin
|
2376 |
|
|
shift_out = shift_filler[15:0];
|
2377 |
|
|
shift_rollover = shift_in[15];
|
2378 |
|
|
end
|
2379 |
12 |
rehayes |
|
2380 |
2 |
rehayes |
// Start Left Shifts
|
2381 |
12 |
rehayes |
|
2382 |
2 |
rehayes |
6'b1_0_0000 :
|
2383 |
|
|
begin
|
2384 |
|
|
shift_out = shift_in;
|
2385 |
|
|
shift_rollover = 1'b0;
|
2386 |
|
|
end
|
2387 |
|
|
6'b1_0_0001 :
|
2388 |
|
|
begin
|
2389 |
|
|
shift_out = {shift_in[14:0], shift_filler[15]};
|
2390 |
|
|
shift_rollover = shift_in[15];
|
2391 |
|
|
end
|
2392 |
|
|
6'b1_0_0010 :
|
2393 |
|
|
begin
|
2394 |
|
|
shift_out = {shift_in[13:0], shift_filler[15:14]};
|
2395 |
|
|
shift_rollover = shift_in[14];
|
2396 |
|
|
end
|
2397 |
|
|
6'b1_0_0011 :
|
2398 |
|
|
begin
|
2399 |
|
|
shift_out = {shift_in[12:0], shift_filler[15:13]};
|
2400 |
|
|
shift_rollover = shift_in[13];
|
2401 |
|
|
end
|
2402 |
|
|
6'b1_0_0100 :
|
2403 |
|
|
begin
|
2404 |
|
|
shift_out = {shift_in[11:0], shift_filler[15:12]};
|
2405 |
|
|
shift_rollover = shift_in[12];
|
2406 |
|
|
end
|
2407 |
|
|
6'b1_0_0101 :
|
2408 |
|
|
begin
|
2409 |
|
|
shift_out = {shift_in[10:0], shift_filler[15:11]};
|
2410 |
|
|
shift_rollover = shift_in[11];
|
2411 |
|
|
end
|
2412 |
|
|
6'b1_0_0110 :
|
2413 |
|
|
begin
|
2414 |
|
|
shift_out = {shift_in[ 9:0], shift_filler[15:10]};
|
2415 |
|
|
shift_rollover = shift_in[10];
|
2416 |
|
|
end
|
2417 |
|
|
6'b1_0_0111 :
|
2418 |
|
|
begin
|
2419 |
|
|
shift_out = {shift_in[ 8:0], shift_filler[15: 9]};
|
2420 |
|
|
shift_rollover = shift_in[ 9];
|
2421 |
|
|
end
|
2422 |
|
|
6'b1_0_1000 :
|
2423 |
|
|
begin
|
2424 |
|
|
shift_out = {shift_in[ 7:0], shift_filler[15: 8]};
|
2425 |
|
|
shift_rollover = shift_in[ 8];
|
2426 |
|
|
end
|
2427 |
|
|
6'b1_0_1001 :
|
2428 |
|
|
begin
|
2429 |
|
|
shift_out = {shift_in[ 6:0], shift_filler[15: 7]};
|
2430 |
|
|
shift_rollover = shift_in[ 7];
|
2431 |
|
|
end
|
2432 |
|
|
6'b1_0_1010 :
|
2433 |
|
|
begin
|
2434 |
|
|
shift_out = {shift_in[ 5:0], shift_filler[15: 6]};
|
2435 |
|
|
shift_rollover = shift_in[ 6];
|
2436 |
|
|
end
|
2437 |
|
|
6'b1_0_1011 :
|
2438 |
|
|
begin
|
2439 |
|
|
shift_out = {shift_in[ 4:0], shift_filler[15: 5]};
|
2440 |
|
|
shift_rollover = shift_in[ 5];
|
2441 |
|
|
end
|
2442 |
|
|
6'b1_0_1100 :
|
2443 |
|
|
begin
|
2444 |
|
|
shift_out = {shift_in[ 3:0], shift_filler[15 :4]};
|
2445 |
|
|
shift_rollover = shift_in[ 4];
|
2446 |
|
|
end
|
2447 |
|
|
6'b1_0_1101 :
|
2448 |
|
|
begin
|
2449 |
|
|
shift_out = {shift_in[ 2:0], shift_filler[15: 3]};
|
2450 |
|
|
shift_rollover = shift_in[ 3];
|
2451 |
|
|
end
|
2452 |
|
|
6'b1_0_1110 :
|
2453 |
|
|
begin
|
2454 |
|
|
shift_out = {shift_in[ 1:0], shift_filler[15: 2]};
|
2455 |
|
|
shift_rollover = shift_in[ 2];
|
2456 |
|
|
end
|
2457 |
|
|
6'b1_0_1111 :
|
2458 |
|
|
begin
|
2459 |
|
|
shift_out = {shift_in[ 0], shift_filler[15: 1]};
|
2460 |
|
|
shift_rollover = shift_in[ 1];
|
2461 |
|
|
end
|
2462 |
|
|
6'b1_1_???? :
|
2463 |
|
|
begin
|
2464 |
|
|
shift_out = shift_filler[15: 0];
|
2465 |
|
|
shift_rollover = shift_in[ 0];
|
2466 |
|
|
end
|
2467 |
|
|
endcase
|
2468 |
12 |
rehayes |
|
2469 |
|
|
|
2470 |
2 |
rehayes |
endmodule // xgate_barrel_shift
|
2471 |
|
|
|
2472 |
|
|
// -----------------------------------------------------------------------------
|
2473 |
|
|
// -----------------------------------------------------------------------------
|
2474 |
|
|
// -----------------------------------------------------------------------------
|
2475 |
|
|
|
2476 |
|
|
module semaphore_bit #(parameter NO_LOCK = 2'b00,
|
2477 |
|
|
parameter RISC_LOCK = 2'b10,
|
2478 |
12 |
rehayes |
parameter HOST_LOCK = 2'b11)
|
2479 |
2 |
rehayes |
(
|
2480 |
|
|
output host_status, // Return status for Host processor
|
2481 |
|
|
output risc_status, // Return Status for RISC processor
|
2482 |
|
|
|
2483 |
|
|
input risc_clk, // Semaphore register clock
|
2484 |
|
|
input async_rst_b, // Async reset signal
|
2485 |
|
|
input risc_bit_sel, // Bit selected by RISC
|
2486 |
|
|
input csem, // RISC Clear Semaphore Bit
|
2487 |
|
|
input ssem, // RISC Set Semaphore Bit
|
2488 |
|
|
input host_wrt, // Host write to the Semaphore Register
|
2489 |
|
|
input host_bit_mask, // Host mask bit written to the Semaphore bit
|
2490 |
|
|
input host_bit // Host bit written to the Semaphore bit
|
2491 |
|
|
);
|
2492 |
|
|
|
2493 |
|
|
reg [1:0] next_semap_state;
|
2494 |
|
|
reg [1:0] semap_state;
|
2495 |
12 |
rehayes |
|
2496 |
2 |
rehayes |
assign host_status = semap_state == HOST_LOCK;
|
2497 |
|
|
assign risc_status = ssem && risc_bit_sel && ((semap_state == RISC_LOCK) || (next_semap_state == RISC_LOCK));
|
2498 |
|
|
|
2499 |
|
|
always @(posedge risc_clk or negedge async_rst_b)
|
2500 |
|
|
if (!async_rst_b)
|
2501 |
|
|
semap_state <= NO_LOCK;
|
2502 |
|
|
else
|
2503 |
|
|
semap_state <= next_semap_state;
|
2504 |
|
|
|
2505 |
|
|
always @*
|
2506 |
|
|
begin
|
2507 |
|
|
case(semap_state)
|
2508 |
12 |
rehayes |
NO_LOCK:
|
2509 |
|
|
begin
|
2510 |
|
|
if (host_wrt && host_bit_mask && host_bit)
|
2511 |
|
|
next_semap_state = HOST_LOCK;
|
2512 |
|
|
else if (ssem && risc_bit_sel)
|
2513 |
|
|
next_semap_state = RISC_LOCK;
|
2514 |
|
|
else
|
2515 |
|
|
next_semap_state = NO_LOCK;
|
2516 |
|
|
end
|
2517 |
|
|
RISC_LOCK:
|
2518 |
|
|
begin
|
2519 |
|
|
if (csem && risc_bit_sel)
|
2520 |
|
|
next_semap_state = NO_LOCK;
|
2521 |
26 |
rehayes |
else
|
2522 |
|
|
next_semap_state = RISC_LOCK;
|
2523 |
|
|
end
|
2524 |
12 |
rehayes |
HOST_LOCK:
|
2525 |
|
|
begin
|
2526 |
|
|
if (host_wrt && host_bit_mask && !host_bit)
|
2527 |
|
|
next_semap_state = NO_LOCK;
|
2528 |
26 |
rehayes |
else
|
2529 |
|
|
next_semap_state = HOST_LOCK;
|
2530 |
|
|
end
|
2531 |
12 |
rehayes |
default:
|
2532 |
|
|
next_semap_state = NO_LOCK;
|
2533 |
2 |
rehayes |
endcase
|
2534 |
|
|
end
|
2535 |
12 |
rehayes |
|
2536 |
2 |
rehayes |
endmodule // semaphore_bit
|
2537 |
|
|
|
2538 |
|
|
|