OpenCores
URL https://opencores.org/ocsvn/light52/light52/trunk

Subversion Repositories light52

[/] [light52/] [trunk/] [vhdl/] [light52_alu.vhdl] - Blame information for rev 23

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ja_rd
--------------------------------------------------------------------------------
2
-- light52_alu.vhdl -- ALU and its input operand multiplexors.
3
--------------------------------------------------------------------------------
4
-- This module contains the ALU, its input operand registers (called T and V)
5
-- and the input multiplexors for those registers.
6
-- It contains the ACC and B SFRs, whose operation is tightly coupled to the 
7
-- ALU functionality.
8
--
9
-- Note that the ALU has a strong dependence on the CPU state machine: the 
10
-- state is used to control the input register multiplexors, to sequence the 
11
-- operation of the DA function and to control when (and with what) the ACC
12
-- is loaded.
13
--
14
--------------------------------------------------------------------------------
15
-- GENERICS:
16
--
17
-- IMPLEMENT_BCD_INSTRUCTIONS   -- Whether or not to implement BCD instructions.
18
--  When true, instructions DA and XCHD will work as in the original MCS51.
19
--  When false, those instructions will work as NOP, saving some logic.
20
--
21
-- SEQUENTIAL_MULTIPLIER        -- Sequential vs. combinational multiplier.
22
--  When true, a sequential implementation will be used for the multiplier, 
23
--  which will usually save a lot of logic or a dedicated multiplier.
24
--  When false, a combinational registered multiplier will be used.
25
--  (NOT IMPLEMENTED -- setting it to true will raise an assertion failure).
26
--
27
--------------------------------------------------------------------------------
28
-- SIGNAL INTERFACE:
29
--
30
-- A description of the many signals will be of little use because most of them
31
-- are self-explaining, I hope. Instead, I will only describe those signals 
32
-- whose purpose may be somewhat more obscure:
33
--
34
-- nobit_result :       ALU result that excludes the 'bit operations' .
35
--                      Used only to load DPTR; it's faster because we bypass
36
--                      the 'bit' mux (DPH & DPL aren't bit addressable).
37
--
38
-- FIXME the ALU needs to be diagrammed and coeumtnted in a design doc.
39
--------------------------------------------------------------------------------
40
-- Copyright (C) 2012 Jose A. Ruiz
41
--
42
-- This source file may be used and distributed without
43
-- restriction provided that this copyright statement is not
44
-- removed from the file and that any derivative work contains
45
-- the original copyright notice and the associated disclaimer.
46
--
47
-- This source file is free software; you can redistribute it
48
-- and/or modify it under the terms of the GNU Lesser General
49
-- Public License as published by the Free Software Foundation;
50
-- either version 2.1 of the License, or (at your option) any
51
-- later version.
52
--
53
-- This source is distributed in the hope that it will be
54
-- useful, but WITHOUT ANY WARRANTY; without even the implied
55
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
56
-- PURPOSE.  See the GNU Lesser General Public License for more
57
-- details.
58
--
59
-- You should have received a copy of the GNU Lesser General
60
-- Public License along with this source; if not, download it
61
-- from http://www.opencores.org/lgpl.shtml
62
--------------------------------------------------------------------------------
63
 
64
library ieee;
65
use ieee.std_logic_1164.all;
66
use ieee.numeric_std.all;
67
 
68
use work.light52_pkg.all;
69
use work.light52_ucode_pkg.all;
70
 
71
entity light52_alu is
72
    generic (
73
        SEQUENTIAL_MULTIPLIER : boolean := false;
74
        IMPLEMENT_BCD_INSTRUCTIONS : boolean := false
75
    );
76
    port(
77
        clk             : in std_logic;
78
        reset           : in std_logic;
79
 
80
        result          : out t_byte;
81
        nobit_result    : out t_byte;
82
 
83
        xdata_wr        : out std_logic_vector(7 downto 0);
84
        xdata_rd        : in std_logic_vector(7 downto 0);
85
 
86
        iram_sfr_rd     : in t_byte;
87
        code_rd         : in std_logic_vector(7 downto 0);
88
        ACC             : out t_byte;
89
        B               : out t_byte;
90
 
91
        cy_in           : in std_logic;
92
        ac_in           : in std_logic;
93
 
94
        result_is_zero  : out std_logic;
95
        acc_is_zero     : out std_logic;
96
        cy_out          : out std_logic;
97
        ov_out          : out std_logic;
98
        p_out           : out std_logic;
99
        op_sel          : in t_alu_op_sel;
100
 
101
 
102
        alu_fn_reg      : in t_alu_fns;
103
        bit_index_reg   : in unsigned(2 downto 0);
104
        load_acc_sfr    : in std_logic;
105
        load_acc_out    : out std_logic;
106
        bit_input_out   : out std_logic;
107
        ac_out          : out std_logic;
108
 
109
        load_b_sfr      : in std_logic;
110
        mul_ready       : out std_logic;
111
        div_ready       : out std_logic;
112
 
113
        use_bitfield    : in std_logic;
114
 
115
        ps              : t_cpu_state
116
    );
117
end entity light52_alu;
118
 
119
 
120
architecture plain of light52_alu is
121
 
122
---- Datapath ------------------------------------------------------------------
123
 
124
-- ALU control signals
125
signal alu_ctrl_fn_arith :  unsigned(2 downto 0);
126
signal alu_ctrl_fn_logic :  unsigned(1 downto 0);
127
signal alu_ctrl_fn_shift :  unsigned(1 downto 0);
128
signal alu_ctrl_mux_2 :     std_logic;
129
signal alu_ctrl_mux_1 :     std_logic;
130
signal alu_ctrl_mux_0 :     std_logic;
131
 
132
-- ALU operands and intermediate results
133
signal alu_op_0 :           t_byte;
134
signal alu_op_sel :         t_alu_op_sel;
135
signal alu_op_1 :           t_byte;
136
-- adder_cy_in: carry input into the adder/subtractor
137
signal adder_cy_in :        std_logic;
138
-- adder_cy_integer: integer version of adder_cy_in.
139
signal adder_cy_integer :   integer range 0 to 1;
140
signal adder_op_0 :         t_ebyte;
141
signal adder_op_1 :         t_ebyte;
142
signal adder_op_1_comp :    t_ebyte;
143
signal alu_adder_result :   t_ebyte;
144
signal alu_logic_result :   t_byte;
145
signal alu_swap_result :    t_byte;
146
signal alu_shift_result :   t_byte;
147
signal alu_ext_result :     t_byte;
148
signal alu_shift_ext_result : t_byte;
149
signal alu_log_shift_result : t_byte;
150
 
151
signal div_ov :             std_logic;
152
signal mul_ov :             std_logic;
153
signal ext_ov :             std_logic;
154
signal arith_ov :           std_logic;
155
signal arith_ov_add :       std_logic;
156
signal arith_ov_sub :       std_logic;
157
 
158
signal bitfield_result :    t_byte;
159
signal bitfield_mask :      t_byte;
160
 
161
signal alu_cy_shift :       std_logic;
162
signal alu_cy_arith :       std_logic;
163
signal alu_cy_arith_shift : std_logic;
164
signal alu_bit_result :     std_logic;
165
signal bit_input :          std_logic;
166
signal P_flag :             std_logic;
167
 
168
 
169
signal alu_result :         t_byte;
170
signal result_internal :    t_byte;
171
 
172
signal alu_bit_fn_reg :     t_bit_fns;
173
 
174
---- CPU programmer's model registers & temp registers -------------------------
175
 
176
signal A_reg :              t_byte;
177
signal B_reg :              t_byte;
178
signal parity_4 :           unsigned(3 downto 0);
179
signal parity_2 :           unsigned(1 downto 0);
180
signal T_reg :              t_byte;
181
signal V_reg :              t_byte;
182
signal P_flag_reg :         std_logic;
183
 
184
signal load_acc_implicit :  std_logic;
185
-- load_acc: asserted for implicit ACC updates and for SFR writes to ACC
186
signal load_acc :           std_logic;
187
signal load_acc_div :       std_logic;
188
signal load_acc_mul :       std_logic;
189
-- acc_input: value to be loaded on ACC
190
signal acc_input :          t_byte;
191
signal load_t :             std_logic_vector(1 downto 0);
192
signal load_v :             std_logic;
193
 
194
---- Interface to MUL/DIV unit -------------------------------------------------
195
 
196
signal product :            t_word;
197
signal quotient :           t_byte;
198
signal remainder :          t_byte;
199
signal start_muldiv :       std_logic;
200
signal mul_ready_internal : std_logic;
201
signal div_ready_internal : std_logic;
202
 
203
---- BCD logic -----------------------------------------------------------------
204
 
205
signal da_add :             unsigned(8 downto 0);
206
signal da_add_lsn :         unsigned(3 downto 0);
207
signal da_add_msn :         unsigned(3 downto 0);
208
signal A_reg_ext :          unsigned(8 downto 0);
209
signal da_res :             unsigned(8 downto 0);
210
signal da_cy :              std_logic;
211
signal da_int_cy :          std_logic;
212
signal ext_cy :             std_logic;
213
 
214
signal xchd_res :           unsigned(7 downto 0);
215
 
216
-- Function to compute carry out of a given adder stage
217
function carry_stage(sub:  std_logic;
218
                     a_in: std_logic;
219
                     b_in: std_logic;
220
                     outp: std_logic) return std_logic is
221
variable bits : std_logic_vector(3 downto 0);
222
begin
223
    bits := (sub, a_in, b_in, outp);
224
 
225
    case bits is
226
    when "0010" | "0100" | "0110" | "0111" |
227
         "1001" | "1010" | "1011" | "1101" |
228
         "1111" =>                          return '1';
229
    when others =>                          return '0';
230
    end case;
231
end function carry_stage;
232
 
233
 
234
begin
235
 
236
-- Extract the ALU control bits from the decoded ALU operation code.
237
-- First the function selector code...
238
alu_ctrl_fn_arith <= alu_fn_reg(5 downto 3);
239
alu_ctrl_fn_logic <= alu_fn_reg(4 downto 3);
240
alu_ctrl_fn_shift <= alu_fn_reg(4 downto 3);
241
-- ...then the multiplexor control bits.
242
alu_ctrl_mux_2 <= alu_fn_reg(2);
243
alu_ctrl_mux_1 <= alu_fn_reg(1);
244
alu_ctrl_mux_0 <= alu_fn_reg(0);
245
 
246
 
247
-- Parity logic.
248
-- Note that these intermediate signals will be optimized away; the parity logic
249
-- will take the equivalent of 3 4-input LUTs.
250
parity_4 <= acc_input(7 downto 4) xor acc_input(3 downto 0);
251
 
252
parity_2 <= parity_4(3 downto 2) xor parity_4(1 downto 0);
253
P_flag <= parity_2(1) xor parity_2(0);
254
 
255
parity_flag_register:
256
process(clk)
257
begin
258
    if clk'event and clk='1' then
259
        if reset = '1' then
260
            -- Reset value is unnecessary; we use it so we don't have to argue
261
            -- for an exception to the design rules (@note2).
262
            P_flag_reg <= '0';
263
        else
264
            if load_acc = '1' then
265
                -- Load P flag register whenever ACC is updated.
266
                P_flag_reg <= P_flag;
267
            end if;
268
        end if;
269
    end if;
270
end process parity_flag_register;
271
 
272
p_out <= P_flag_reg;
273
 
274
-- FIXMe move this to some other code section
275
acc_is_zero <= '1' when A_reg=X"00" else '0';
276
 
277
 
278
 
279
 
280
ACC <= A_reg;
281
 
282
xdata_wr <= std_logic_vector(A_reg);
283
 
284
---- Datapath: ALU and ALU operand multiplexors --------------------------------
285
 
286
 
287
-- ALU input operand mux control. All instructions that use the ALU shall
288
-- have a say in this logic through the state machine register.
289
with ps select alu_op_sel <=
290
    AI_A_T              when cjne_a_imm_1,
291
    AI_A_T              when cjne_a_dir_2,
292
    AI_V_T              when cjne_ri_imm_4,
293
    AI_V_T              when cjne_rn_imm_2,
294
    AI_T_0              when djnz_dir_2,
295
    AI_T_0              when djnz_dir_3,
296
    AI_T_0              when push_2,
297
    AI_T_0              when mov_dptr_1,
298
    AI_T_0              when mov_dptr_2,
299
    AI_A_0              when xch_2,
300
    AI_T_0              when xch_3,
301
    AI_A_T              when alu_xchd_4 | alu_xchd_5,
302
    op_sel              when others; -- by default, use logic for ALU class
303
 
304
 
305
-- ALU input operand multiplexor: OP0 can be A, V or T.
306
with alu_op_sel(3 downto 2) select alu_op_0 <=
307
    A_reg           when "01",
308
    V_reg           when "10",
309
    T_reg           when others;
310
 
311
-- ALU input operand multiplexor: OP1 can be T or 0.
312
with alu_op_sel(1 downto 0) select alu_op_1 <=
313
    T_reg           when "01",
314
    X"00"           when others;
315
 
316
 
317
-- Datapath: ALU ---------------------------------------------------------------
318
 
319
-- ALU: logic operations (1-LUT deep)
320
with alu_ctrl_fn_logic select alu_logic_result <=
321
    alu_op_0 and alu_op_1       when "00",
322
    alu_op_0 or  alu_op_1       when "01",
323
    alu_op_0 xor alu_op_1       when "10",
324
    not alu_op_0                when others;
325
 
326
-- ALU: SWAP logic; operates on logic result
327
with alu_ctrl_mux_2 select alu_swap_result <=
328
    alu_logic_result(3 downto 0) & alu_logic_result(7 downto 4) when '1',
329
    alu_logic_result                                            when others;
330
 
331
-- ALU: shift operations
332
with alu_ctrl_fn_shift select alu_shift_result <=
333
    alu_op_0(0) & alu_op_0(7 downto 1)      when "00",      -- RR
334
    cy_in & alu_op_0(7 downto 1)            when "01",      -- RRC
335
    alu_op_0(6 downto 0) & alu_op_0(7)      when "10",      -- RL
336
    alu_op_0(6 downto 0) & cy_in            when others;    -- RLC
337
 
338
with alu_ctrl_fn_logic(1) select alu_cy_shift <=
339
    alu_op_0(0) when '0',
340
    alu_op_0(7) when others;
341
 
342
-- ALU: adder/subtractor (2 LUTs deep, 8-bit carry chain)
343
 
344
-- Carry/borrow input, accounting for all operations that need it
345
with alu_ctrl_fn_arith(2 downto 0) select adder_cy_in <=
346
    '0'             when "000", -- ADD
347
    '1'             when "001", -- SUB
348
    cy_in           when "010", -- ADDC
349
    not cy_in       when "011", -- SUBB
350
    '1'             when "110", -- INC
351
    '0'             when others;-- DEC
352
 
353
-- Note we do zero-extension and not sign-extension because we just want to
354
-- get the value of CY from bit 7 and this is most easily done with zero-ext.
355
 
356
-- ALU operands are ZERO extended before entering the adder...
357
adder_op_0 <= '0' & alu_op_0;
358
-- ...and op1 (subtrahend) is negated for substract operations.
359
-- Note this is a complement-to-1 only; we need to adjust the carry input for
360
-- the adder op to be performed (see @note5).
361
with alu_ctrl_fn_arith(0) select adder_op_1_comp <=
362
    ('0' & alu_op_1)        when '0',
363
    ('1' & not alu_op_1)    when others;
364
-- The adder carry input needs some syntactic trickery: std_logic to integer.
365
adder_cy_integer <= 1 when adder_cy_in='1' else 0;
366
 
367
adder_op_1 <= adder_op_1_comp;-- + adder_cy_integer;
368
-- This is the actual adder/subtractor.
369
alu_adder_result <= adder_op_0 + adder_op_1 + adder_cy_integer;
370
 
371
-- Compute OV by comparing operand and result signs.
372
arith_ov_add <= '1' when
373
    (alu_op_0(7)='0' and alu_op_1(7)='0' and alu_adder_result(7)='1') or
374
    (alu_op_0(7)='1' and alu_op_1(7)='1' and alu_adder_result(7)='0')
375
    else '0';
376
 
377
arith_ov_sub <= '1' when
378
    (alu_op_0(7)='0' and alu_op_1(7)='1' and alu_adder_result(7)='1') or
379
    (alu_op_0(7)='1' and alu_op_1(7)='0' and alu_adder_result(7)='0')
380
    else '0';
381
 
382
arith_ov <= arith_ov_add when alu_ctrl_fn_arith(0)='0' else arith_ov_sub;
383
 
384
-- Carry/borrow output is the 9th bit of the result.
385
alu_cy_arith <= alu_adder_result(8);
386
 
387
-- This is the 'half carry' or 'aux carry': carry out of stage 3.
388
ac_out <= carry_stage(alu_ctrl_fn_arith(0),
389
                      alu_op_0(3),alu_op_1(3),
390
                      alu_adder_result(3));
391
 
392
 
393
 
394
-- ALU: result path multiplexors
395
 
396
with alu_ctrl_mux_2 select alu_shift_ext_result <=
397
    alu_ext_result      when '1',
398
    alu_shift_result    when others;
399
 
400
with alu_ctrl_mux_1 select alu_log_shift_result <=
401
    alu_swap_result         when '0',
402
    alu_shift_ext_result    when others;
403
 
404
with alu_ctrl_mux_0 select alu_result <=
405
    alu_log_shift_result            when '0',
406
    alu_adder_result(7 downto 0)    when others;
407
 
408
 
409
alu_cy_arith_shift <= alu_cy_arith when alu_ctrl_mux_0='1' else alu_cy_shift;
410
 
411
ext_cy <= da_cy when ps=alu_daa_1 or ps=alu_daa_0 else '0';
412
 
413
with alu_fn_reg(2 downto 0) select cy_out <=
414
    alu_bit_result      when "011" | "111", -- bit operations
415
    ext_cy              when "110",         -- mul/div/bcd
416
    alu_cy_arith_shift  when others;
417
 
418
with alu_fn_reg(3) select ext_ov <=
419
    mul_ov  when '0',
420
    div_ov  when others;
421
 
422
with alu_fn_reg(2 downto 0) select ov_out <=
423
    ext_ov          when "110", -- mul/div
424
    arith_ov        when others;
425
 
426
result_is_zero <= '1' when alu_result=X"00" else '0';
427
 
428
 
429
-- Datapath: BIT ALU -----------------------------------------------------------
430
 
431
 
432
bit_input <= T_reg(to_integer(bit_index_reg));
433
bit_input_out <= bit_input;
434
 
435
-- Extract BIT ALU operation selector encoded into ALU operation field.
436
alu_bit_fn_reg <= alu_fn_reg(5 downto 2);
437
 
438
-- Part of the BIT ALU: unary/binary operations between C and bit_input.
439
with alu_bit_fn_reg select alu_bit_result <=
440
    '0'                         when AB_CLR,
441
    '1'                         when AB_SET,
442
    not cy_in                   when AB_CPLC,
443
    cy_in                       when AB_C,
444
    bit_input                   when AB_B,
445
    bit_input and cy_in         when AB_ANL,
446
    bit_input or cy_in          when AB_ORL,
447
    (not bit_input) and cy_in   when AB_ANL_NB,
448
    (not bit_input) or cy_in    when AB_ORL_NB,
449
    not bit_input               when others;
450
 
451
-- Highlight the operand bit within its byte. Useful when reassembling the
452
-- byte after operating on the bit. This should synth as an 8-LUT block.
453
with bit_index_reg select bitfield_mask <=
454
    "10000000" when "111",
455
    "01000000" when "110",
456
    "00100000" when "101",
457
    "00010000" when "100",
458
    "00001000" when "011",
459
    "00000100" when "010",
460
    "00000010" when "001",
461
    "00000001" when others;
462
 
463
-- Reassemble the byte; replace the operand bit with the op result and leave
464
-- all other bits unchanged. Ideally this is a single LUT row.
465
bitfield_mask_logic:
466
for i in 0 to 7 generate
467
    bitfield_result(i) <=
468
        alu_bit_result when bitfield_mask(i)='1' else
469
        T_reg(i);
470
end generate;
471
 
472
 
473
-- Datapath: ALU result load enable signals ------------------------------------
474
 
475
nobit_result <= alu_result; -- FIXME remove remnants of this
476
 
477
with use_bitfield select result_internal <=
478
    bitfield_result     when '1',
479
    alu_result          when others;
480
 
481
result <= result_internal;
482
 
483
-- Assert load_acc_implicit for all states that update ACC implicitly, that is,
484
-- do not account for SFR accesses to ACC.
485
with ps select load_acc_implicit <=
486
    '1' when alu_res_to_a,
487
    '1' when movx_a_dptr_0,
488
    '1' when movx_a_ri_3,
489
    '1' when movc_1,
490
    '1' when xch_3,
491
    '1' when alu_xchd_5,
492
    '1' when alu_daa_0 | alu_daa_1,
493
    '0' when others;
494
 
495
 
496
load_acc_mul <= '1' when ps=alu_mul_0 and mul_ready_internal='1' else '0';
497
load_acc_div <= '1' when ps=alu_div_0 and div_ready_internal='1' else '0';
498
 
499
-- ACC will be loaded by implicit addressing and by explicit SFR addressing.
500
-- Note the data source is the same in both cases.
501
load_acc <= load_acc_implicit or load_acc_sfr or load_acc_mul or load_acc_div;
502
load_acc_out <= load_acc;
503
-- FIXME explain
504
with ps select acc_input <=
505
    unsigned(xdata_rd)      when movx_a_dptr_0 | movx_a_ri_3,
506
    unsigned(code_rd)       when movc_1,
507 23 ja_rd
    result_internal         when others;
508 2 ja_rd
 
509 23 ja_rd
 
510 2 ja_rd
ACC_register:
511
process(clk)
512
begin
513
    if clk'event and clk='1' then
514
        if reset = '1' then
515
            A_reg <= (others => '0');
516
        elsif load_acc='1' then
517
            A_reg <= acc_input;
518
        end if;
519
    end if;
520
end process ACC_register;
521
 
522
-- T_reg will have the 2nd alu operand when needed: #imm, dir or xram data
523
with ps select load_t <=
524
    -- Load T with RAM/SFR data...
525
    "10" when alu_ram_to_t_code_to_ab,
526
    "10" when alu_ram_to_t_rx_to_ab,
527
    "10" when alu_ram_to_t,
528
    "10" when cjne_a_dir_1,
529
    "10" when djnz_dir_1,
530
    "10" when jrb_bit_1,
531
    "10" when bit_op_1,
532
    "10" when push_1,
533
    "10" when pop_1,
534
    "10" when xch_1,
535
    "10" when alu_xchd_3,
536
    -- ... or with #imm data...
537
    "11" when alu_ram_to_v_code_to_t,
538
    "11" when alu_code_to_t_rx_to_ab,
539
    "11" when alu_code_to_t,
540
    "11" when cjne_a_imm_0,
541
    "11" when cjne_rn_imm_1,
542
    "11" when cjne_ri_imm_3,
543
    "11" when mov_dptr_0,
544
    "11" when mov_dptr_1,
545
    -- ...or don't load T
546
    "00" when others;
547
 
548
with ps select load_v <=
549
    '1' when alu_ram_to_v_code_to_t,
550
    '1' when cjne_ri_imm_3,
551
    '1' when cjne_rn_imm_1,
552
    '0' when others;
553
 
554
-- FIXME Temp registers have no reset value.
555
TEMP_registers:
556
process(clk)
557
begin
558
    if clk'event and clk='1' then
559
        if load_t(1)='1' then
560
            if load_t(0)='1' then
561
                T_reg <= unsigned(code_rd); -- #imm data
562
            else
563
                T_reg <= unsigned(iram_sfr_rd); -- [dir] data
564
            end if;
565
        end if;
566
 
567
        if load_v='1' then
568
            V_reg <= unsigned(iram_sfr_rd);
569
        end if;
570
    end if;
571
end process TEMP_registers;
572
 
573
-- Multiplication/division unit ------------------------------------------------
574
 
575
muldiv : entity work.light52_muldiv
576
generic map (
577
    SEQUENTIAL_MULTIPLIER => SEQUENTIAL_MULTIPLIER
578
)
579
port map (
580
    clk =>              clk,
581
    reset =>            reset,
582
 
583
    data_a =>           A_reg,
584
    data_b =>           B_reg,
585
    start =>            start_muldiv,
586
 
587
    prod_out =>         product,
588
    quot_out =>         quotient,
589
    rem_out =>          remainder,
590
    div_ov_out =>       div_ov,
591
    mul_ov_out =>       mul_ov,
592
 
593
    mul_ready =>        mul_ready_internal,
594
    div_ready =>        div_ready_internal
595
);
596
 
597
start_muldiv <= load_acc or load_b_sfr;
598
 
599
 
600
mul_ready <= mul_ready_internal;
601
div_ready <= div_ready_internal;
602
 
603
b_register:
604
process(clk)
605
begin
606
    if clk'event and clk='1' then
607
        if load_b_sfr='1' then
608
            B_reg <= result_internal;
609
        elsif load_acc_mul='1' then
610
            B_reg <= product(15 downto 8);
611
        elsif load_acc_div='1' then
612
            B_reg <= remainder;
613
        end if;
614
    end if;
615
end process b_register;
616
 
617
B <= B_reg;
618
 
619
full_alu_mux:
620
if IMPLEMENT_BCD_INSTRUCTIONS generate
621
with ps select alu_ext_result <=
622
    quotient                when alu_div_0,
623
    da_res(7 downto 0)      when alu_daa_0 | alu_daa_1,
624
    xchd_res                when alu_xchd_4 | alu_xchd_5,
625
    product(7 downto 0)     when others;
626
end generate;
627
 
628
unimplemented_bcd_alu_mux:
629
if not IMPLEMENT_BCD_INSTRUCTIONS generate
630
with ps select alu_ext_result <=
631
    quotient                when alu_div_0,
632
    product(7 downto 0)     when others;
633
end generate;
634
 
635
---- BCD logic -----------------------------------------------------------------
636
 
637
 
638
bcd_logic:
639
if IMPLEMENT_BCD_INSTRUCTIONS generate
640
 
641
-- DA logic ---------- Done in 2 cycles mimicking the datasheet description.
642
 
643
-- IF A(low)>9 OR AC='1' then A+=0x06. This is done in state alu_daa_0.
644
da_add_lsn <= "0110" when (ac_in='1' or to_integer(A_reg(3 downto 0))>9) and
645
                          ps=alu_daa_0
646
              else "0000";
647
 
648
-- IF A(high)>9 OR the previous addition of 0x06 generated a carry OR 
649
-- the carry flag was already set, then A+=0x60. Done in state alu_daa_1.
650
da_add_msn <= "0110" when (da_int_cy='1' or cy_in='1' or
651
                           to_integer(A_reg(7 downto 4))>9) and
652
                          ps=alu_daa_1
653
              else "0000";
654
 
655
da_add <= '0' & da_add_msn & da_add_lsn;
656
A_reg_ext <= '0' & A_reg;
657
da_res <= A_reg_ext + da_add;
658
 
659
-- Carry generated in the 1st state od DAA
660
da_cy_ff:
661
process(clk)
662
begin
663
    if clk'event and clk='1' then
664
        da_int_cy <= da_res(8);
665
    end if;
666
end process da_cy_ff;
667
 
668
-- Final carry is 1 if either sum generated a carry OR if it was already set.
669
da_cy <= (da_res(8) xor da_int_cy) or cy_in;
670
 
671
 
672
-- XCHD logic --------- Done in 2 cycles to simplify the state machine.
673
 
674
-- This operation is state-dependent. An ugly hack that saves logic.
675
with ps select xchd_res <=
676
    alu_op_1(7 downto 4) & alu_op_0(3 downto 0)     when alu_xchd_4,
677
    alu_op_0(7 downto 4) & alu_op_1(3 downto 0)     when others;
678
 
679
 
680
end generate;
681
 
682
dummy_bcd_logic:
683
if not IMPLEMENT_BCD_INSTRUCTIONS generate
684
da_cy <= '0';
685
end  generate;
686
 
687
 
688
 
689
end architecture plain;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.