-- ###----------------------------------------------------------------###
-- #									#
-- # file	: dlxm.vbe						#
-- # date	: Jan 26 1994						#
-- # version	: v0.1							#
-- # descr.	: VHDL description of the DLX's data-path (micro-	#
-- #		  programmed implementation)				#
-- #									#
-- ###----------------------------------------------------------------###

entity DLXM is

  port (
       CK      : in    bit                         ;
       RESET   : in    bit                         ;
       FRZ     : in    bit                         ;
       IT      : in    bit_vector ( 3 downto 0)    ;
       DATA    : inout mux_vector (31 downto 0) bus;
       BYTE    : out   bit_vector ( 0     to 3)    ;
       RW      : out   bit                         ;
       ADR     : out   mux_vector(31 downto 0)  bus;
       SCIN    : in    bit                         ;
       TEST    : in    bit                         ;
       SCOUT   : out   bit                         ;
       VDD     : in    bit                         ;
       VSS     : in    bit                         ;
       VDDP    : in    bit                         ;
       VSSP    : in    bit
       ) ;

end DLXM ;





architecture BEHAVIOURAL of DLXM is

signal CKFRZ_S  : bit                              ;	-- internal clock
signal CK_S     : bit                              ;	-- internal clock
signal CKDLY0_S : bit                              ;	-- internal clock
signal CKDLY1_S : bit                              ;	-- internal clock
signal CKDLY2_S : bit                              ;	-- internal clock
signal CKDLY3_S : bit                              ;	-- internal clock
signal CKDLY4_S : bit                              ;	-- internal clock
signal CKDLY5_S : bit                              ;	-- internal clock
signal CKDLY6_S : bit                              ;	-- internal clock

signal MICADR_S : bit_vector ( 5 downto 0)         ;	-- next micro ins. adr.
signal MICADR_R : reg_vector ( 5 downto 0) register;	-- micro ins. adr reg.
signal MICINS_S : bit_vector (25 downto 0)         ;	-- next  micro ins.
signal RESTMI_X : bit_vector (25 downto 0)         ;	-- reset micro ins.
signal MICINS_R : reg_vector (25 downto 0) register;	-- micro ins. reg.

signal CTLOPX_S : bit_vector ( 3 downto 0)         ;	-- operand x  field
signal CTLOPY_S : bit_vector ( 2 downto 0)         ;	-- operand y  field
signal CTLALU_S : bit_vector ( 3 downto 0)         ;	-- alu        field
signal CTLRES_S : bit_vector ( 3 downto 0)         ;	-- result     field
signal CTLRW_S  : bit_vector ( 3 downto 0)         ;	-- read/write field
signal CTLSEQ_S : bit_vector ( 6 downto 0)         ;	-- sequencer  field

signal REDPNT_S : bit_vector ( 4 downto 0)         ;	-- read pointer
signal WRTPNT_S : bit_vector ( 4 downto 0)         ;	-- write pointer
signal REDREG_S : bit_vector (31 downto 0)         ;	-- value read from reg.
signal IFORMT_S : bit                              ;	-- i format instr.

signal IR_R     : reg_vector (31 downto 0) register;	-- instruction reg.
signal OPCOD_S  : bit_vector ( 5 downto 0)         ;	-- oper. code

signal R1_R     : reg_vector (31 downto 0) register;	-- integer reg #1
signal R2_R     : reg_vector (31 downto 0) register;	-- integer reg #2
signal R3_R     : reg_vector (31 downto 0) register;	-- integer reg #3
signal R4_R     : reg_vector (31 downto 0) register;	-- integer reg #4
signal R5_R     : reg_vector (31 downto 0) register;	-- integer reg #5
signal R6_R     : reg_vector (31 downto 0) register;	-- integer reg #6
signal R7_R     : reg_vector (31 downto 0) register;	-- integer reg #7
signal R8_R     : reg_vector (31 downto 0) register;	-- integer reg #8
signal R9_R     : reg_vector (31 downto 0) register;	-- integer reg #9
signal R10_R    : reg_vector (31 downto 0) register;	-- integer reg #10
signal R11_R    : reg_vector (31 downto 0) register;	-- integer reg #11
signal R12_R    : reg_vector (31 downto 0) register;	-- integer reg #12
signal R13_R    : reg_vector (31 downto 0) register;	-- integer reg #13
signal R14_R    : reg_vector (31 downto 0) register;	-- integer reg #14
signal R15_R    : reg_vector (31 downto 0) register;	-- integer reg #15
signal R16_R    : reg_vector (31 downto 0) register;	-- integer reg #16
signal R17_R    : reg_vector (31 downto 0) register;	-- integer reg #17
signal R18_R    : reg_vector (31 downto 0) register;	-- integer reg #18
signal R19_R    : reg_vector (31 downto 0) register;	-- integer reg #19
signal R20_R    : reg_vector (31 downto 0) register;	-- integer reg #20
signal R21_R    : reg_vector (31 downto 0) register;	-- integer reg #21
signal R22_R    : reg_vector (31 downto 0) register;	-- integer reg #22
signal R23_R    : reg_vector (31 downto 0) register;	-- integer reg #23
signal R24_R    : reg_vector (31 downto 0) register;	-- integer reg #24
signal R25_R    : reg_vector (31 downto 0) register;	-- integer reg #25
signal R26_R    : reg_vector (31 downto 0) register;	-- integer reg #26
signal R27_R    : reg_vector (31 downto 0) register;	-- integer reg #27
signal R28_R    : reg_vector (31 downto 0) register;	-- integer reg #28
signal R29_R    : reg_vector (31 downto 0) register;	-- integer reg #29
signal R30_R    : reg_vector (31 downto 0) register;	-- integer reg #30
signal R31_R    : reg_vector (31 downto 0) register;	-- integer reg #31

signal PC_R     : reg_vector (31 downto 0) register;	-- progr. counter
signal AD_R     : reg_vector (31 downto 0) register;	-- address register
signal IAR_R    : reg_vector (31 downto 0) register;	-- intr. adr. reg.
signal SR_R     : reg_vector (31 downto 0) register;	-- status register
signal TVR_R    : reg_vector (31 downto 0) register;	-- trap vector reg.
signal DT_R     : reg_vector (31 downto 0) register;	-- data register

signal OPERY_S  : bit_vector (31 downto 0)         ;	-- y operand
signal OPERX_S  : bit_vector (31 downto 0)         ;	-- x operand

signal ADDY_S   : bit_vector (31 downto 0)         ;	-- adder's y operand
signal ADDX_S   : bit_vector (31 downto 0)         ;	-- adder's x operand
signal ADDRES_S : bit_vector (31 downto 0)         ;	-- adder's result
signal ADDCRY_S : bit_vector (32 downto 0)         ;	-- adder's carry
signal ADDOVR_S : bit                              ;	-- adder's overflow

signal SEQ_S    : bit                              ;	-- x  = y arith.
signal SNE_S    : bit                              ;	-- x /= y arith.
signal SGE_S    : bit                              ;	-- x >= y arith.
signal SGT_S    : bit                              ;	-- x  > y arith.
signal SLE_S    : bit                              ;	-- x <= y arith.
signal SLT_S    : bit                              ;	-- x  < y arith.

signal SHIN_S   : bit_vector (31 downto 0)         ;	-- shift right in
signal SHRIT_S  : bit_vector (31 downto 0)         ;	-- shift result (right)
signal SHLFT_S  : bit_vector (31 downto 0)         ;	-- shift result (left)

signal RESULT_S : bit_vector (31 downto 0)         ;	-- alu's result
signal RESNUL_S : bit                              ;	-- alu's result = 0

signal IMD16_S  : bit_vector (31 downto 0)         ;	-- signed 16 bit imd
signal IMD18_S  : bit_vector (31 downto 0)         ;	-- short branch offset
signal IMD28_S  : bit_vector (31 downto 0)         ;	-- long  branch offset

signal WORD_S   : bit                              ;
signal BYTE_S   : bit                              ;
signal BYTSEL_S : bit_vector ( 0     to 3)         ;

signal REDDAT_S : bit_vector (31 downto 0)         ;	-- aligned data
signal NEWSR_X  : bit_vector (15 downto 0)         ;	-- new status

signal WENSR_S  : bit                              ;	-- status reg. wen.
signal WENIAR_S : bit                              ;	-- it. adr. reg. wen.
signal WENTVR_S : bit                              ;	-- trap vec. reg. wen.
signal WENPC_S  : bit                              ;	-- progr. counter wen.
signal WENAD_S  : bit                              ;	-- address reg. wen.
signal WENREG_S : bit                              ;	-- integer reg. wen.
signal WENDT_S  : bit                              ;	-- data reg. wen.
signal WENIR_S  : bit                              ;	-- ins. reg. wen.

signal cop1   : bit_vector (3 downto 0) ;
signal cop2   : bit_vector (3 downto 0) ;

signal INTRQS_X : bit                              ;	-- interrupt request
signal EXCRQS_X : bit                              ;	-- exception request
signal RQS_X    : bit                              ;	-- request

signal UNKOPC_X : bit                              ;	-- unknown opcodes
signal PRVINS_X : bit                              ;	-- privileged instr.
signal ILLINS_X : bit                              ;	-- illegal instruction
signal OPVIOL_X : bit                              ;	-- ins. violation
signal OVRFLO_X : bit                              ;	-- overflow
signal DAALGN_X : bit                              ;	-- data adr. algn.
signal DASGMT_X : bit                              ;	-- data adr. segment
signal IAALGN_X : bit                              ;	-- ins. adr. algn.
signal IASGMT_X : bit                              ;	-- ins. adr. segment

signal FRZ_R    : reg_bit                  register;	-- freeze
signal RESET_R  : reg_bit                  register;	-- reset
signal IAV_R    : reg_bit                  register;	-- ins. adr. viol.
signal DAV_R    : reg_bit                  register;	-- data adr. viol.
signal ICO_R    : reg_bit                  register;	-- opcode viol.
signal OVR_R    : reg_bit                  register;	-- overflow
signal IT_R     : reg_vector ( 3 downto 0) register;	-- external it

constant R0_R     : bit_vector (31 downto 0) :=X"00000000"; 	-- reg #0 = 0

constant add_i    : bit_vector (5 downto 0) := B"000_000"  ;	-- add
constant addu_i   : bit_vector (5 downto 0) := B"000_001"  ;	-- addu
constant sub_i    : bit_vector (5 downto 0) := B"000_010"  ;	-- sub
constant subu_i   : bit_vector (5 downto 0) := B"000_011"  ;	-- subu
constant addi_i   : bit_vector (5 downto 0) := B"000_100"  ;	-- addi
constant addui_i  : bit_vector (5 downto 0) := B"000_101"  ;	-- addui
constant subi_i   : bit_vector (5 downto 0) := B"000_110"  ;	-- subi
constant subui_i  : bit_vector (5 downto 0) := B"000_111"  ;	-- subui
constant sll_i    : bit_vector (5 downto 0) := B"001_000"  ;	-- sll
constant srl_i    : bit_vector (5 downto 0) := B"001_001"  ;	-- srl
constant sra_i    : bit_vector (5 downto 0) := B"001_010"  ;	-- sra
constant slli_i   : bit_vector (5 downto 0) := B"001_100"  ;	-- slli
constant srli_i   : bit_vector (5 downto 0) := B"001_101"  ;	-- srli
constant srai_i   : bit_vector (5 downto 0) := B"001_110"  ;	-- srai
constant lhi_i    : bit_vector (5 downto 0) := B"001_111"  ;	-- lhi
constant seq_i    : bit_vector (5 downto 0) := B"010_000"  ;	-- seq
constant sne_i    : bit_vector (5 downto 0) := B"010_001"  ;	-- sne
constant sge_i    : bit_vector (5 downto 0) := B"010_010"  ;	-- sge
constant sle_i    : bit_vector (5 downto 0) := B"010_011"  ;	-- sle
constant seqi_i   : bit_vector (5 downto 0) := B"010_100"  ;	-- seqi
constant snei_i   : bit_vector (5 downto 0) := B"010_101"  ;	-- snei
constant sgei_i   : bit_vector (5 downto 0) := B"010_110"  ;	-- sgei
constant slei_i   : bit_vector (5 downto 0) := B"010_111"  ;	-- slei
constant sgt_i    : bit_vector (5 downto 0) := B"011_010"  ;	-- sgt
constant slt_i    : bit_vector (5 downto 0) := B"011_011"  ;	-- slt
constant sgti_i   : bit_vector (5 downto 0) := B"011_110"  ;	-- sgti
constant slti_i   : bit_vector (5 downto 0) := B"011_111"  ;	-- slti
constant and_i    : bit_vector (5 downto 0) := B"100_000"  ;	-- and
constant or_i     : bit_vector (5 downto 0) := B"100_001"  ;	-- or
constant xor_i    : bit_vector (5 downto 0) := B"100_011"  ;	-- xor
constant andi_i   : bit_vector (5 downto 0) := B"100_100"  ;	-- andi
constant ori_i    : bit_vector (5 downto 0) := B"100_101"  ;	-- ori
constant xori_i   : bit_vector (5 downto 0) := B"100_111"  ;	-- xori

constant sw_i     : bit_vector (5 downto 0) := B"101_000"  ;	-- sw
constant sh_i     : bit_vector (5 downto 0) := B"101_001"  ;	-- sh
constant sb_i     : bit_vector (5 downto 0) := B"101_010"  ;	-- sb
constant lbu_i    : bit_vector (5 downto 0) := B"101_011"  ;	-- lbu
constant lw_i     : bit_vector (5 downto 0) := B"101_100"  ;	-- lw
constant lh_i     : bit_vector (5 downto 0) := B"101_101"  ;	-- lh
constant lb_i     : bit_vector (5 downto 0) := B"101_110"  ;	-- lb
constant lhu_i    : bit_vector (5 downto 0) := B"101_111"  ;	-- lhu

constant jr_i     : bit_vector (5 downto 0) := B"110_000"  ;	-- jr
constant jalr_i   : bit_vector (5 downto 0) := B"110_001"  ;	-- jalr
constant movs2i_i : bit_vector (5 downto 0) := B"110_010"  ;	-- movi2s
constant movi2s_i : bit_vector (5 downto 0) := B"110_011"  ;	-- movs2i
constant beqz_i   : bit_vector (5 downto 0) := B"110_100"  ;	-- beqz
constant bnez_i   : bit_vector (5 downto 0) := B"110_101"  ;	-- bnez
constant j_i      : bit_vector (5 downto 0) := B"111_000"  ;	-- j
constant jal_i    : bit_vector (5 downto 0) := B"111_001"  ;	-- jal
constant rfe_i    : bit_vector (5 downto 0) := B"111_010"  ;	-- rfe
constant trap_i   : bit_vector (5 downto 0) := B"111_011"  ;	-- trap

constant c0     : bit_vector (31 downto 0) := X"00000000";
constant c1     : bit_vector (31 downto 0) := X"00000001";
constant c4     : bit_vector (31 downto 0) := X"00000004";
constant c16    : bit_vector (31 downto 0) := X"00000010";
constant cb     : bit_vector (31 downto 0) := X"000000ff";
constant ch     : bit_vector (31 downto 0) := X"0000ffff";

constant x_rs   : bit_vector (3 downto 0) := B"0000" ;
constant x_rt   : bit_vector (3 downto 0) := B"0001" ;
constant x_pc   : bit_vector (3 downto 0) := B"0100" ;
constant x_ad   : bit_vector (3 downto 0) := B"0101" ;
constant x_sr   : bit_vector (3 downto 0) := B"0110" ;
constant x_tvr  : bit_vector (3 downto 0) := B"0010" ;
constant x_iar  : bit_vector (3 downto 0) := B"0111" ;
constant x_c0   : bit_vector (3 downto 0) := B"1000" ;
constant x_cb   : bit_vector (3 downto 0) := B"1100" ;
constant x_ch   : bit_vector (3 downto 0) := B"1111" ;

constant y_i16  : bit_vector (2 downto 0) := B"000" ;
constant y_i18  : bit_vector (2 downto 0) := B"001" ;
constant y_i28  : bit_vector (2 downto 0) := B"010" ;
constant y_dt   : bit_vector (2 downto 0) := B"011" ;
constant y_ad   : bit_vector (2 downto 0) := B"100" ;
constant y_c0   : bit_vector (2 downto 0) := B"101" ;
constant y_c4   : bit_vector (2 downto 0) := B"110" ;
constant y_c16  : bit_vector (2 downto 0) := B"111" ;

constant a_sum  : bit_vector (3 downto 0) := B"0000" ;
constant a_sumv : bit_vector (3 downto 0) := B"0001" ;
constant a_dif  : bit_vector (3 downto 0) := B"0010" ;
constant a_difv : bit_vector (3 downto 0) := B"0011" ;
constant a_and  : bit_vector (3 downto 0) := B"0100" ;
constant a_or   : bit_vector (3 downto 0) := B"0101" ;
constant a_xor  : bit_vector (3 downto 0) := B"0110" ;
constant a_sll  : bit_vector (3 downto 0) := B"0111" ;
constant a_srl  : bit_vector (3 downto 0) := B"1000" ;
constant a_sra  : bit_vector (3 downto 0) := B"1001" ;
constant a_seq  : bit_vector (3 downto 0) := B"1010" ;
constant a_sne  : bit_vector (3 downto 0) := B"1011" ;
constant a_sge  : bit_vector (3 downto 0) := B"1100" ;
constant a_sgt  : bit_vector (3 downto 0) := B"1101" ;
constant a_sle  : bit_vector (3 downto 0) := B"1110" ;
constant a_slt  : bit_vector (3 downto 0) := B"1111" ;

constant r_no   : bit_vector (3 downto 0) := B"0000" ;
constant r_pc   : bit_vector (3 downto 0) := B"0001" ;
constant r_ad   : bit_vector (3 downto 0) := B"0010" ;
constant r_rd   : bit_vector (3 downto 0) := B"0100" ;
constant r_r31  : bit_vector (3 downto 0) := B"0101" ;
constant r_iar  : bit_vector (3 downto 0) := B"1000" ;
constant r_siar : bit_vector (3 downto 0) := B"1001" ;
constant r_tvr  : bit_vector (3 downto 0) := B"1010" ;
constant r_sr   : bit_vector (3 downto 0) := B"1100" ;
constant r_ssr  : bit_vector (3 downto 0) := B"1101" ;

constant m_no   : bit_vector (3 downto 0) := B"0011" ;
constant m_ftch : bit_vector (3 downto 0) := B"1010" ;
constant m_rw   : bit_vector (3 downto 0) := B"0010" ;
constant m_ww   : bit_vector (3 downto 0) := B"0000" ;
constant m_rb   : bit_vector (3 downto 0) := B"0110" ;
constant m_wb   : bit_vector (3 downto 0) := B"0100" ;

constant s_next : bit_vector (6 downto 0) := B"100_0001" ;
constant s_i2s  : bit_vector (6 downto 0) := B"110_0011" ;
constant s_nnul : bit_vector (6 downto 0) := B"110_0101" ;
constant s_nul  : bit_vector (6 downto 0) := B"110_0111" ;
constant s_s2i  : bit_vector (6 downto 0) := B"111_1001" ;
constant s_mem  : bit_vector (6 downto 0) := B"101_1011" ;
constant s_cod1 : bit_vector (6 downto 0) := B"000_1101" ;
constant s_cod2 : bit_vector (6 downto 0) := B"010_1111" ;
constant s_gt10 : bit_vector (6 downto 0) := B"001000_0" ;
constant s_gt14 : bit_vector (6 downto 0) := B"001100_0" ;
constant s_gt41 : bit_vector (6 downto 0) := B"100001_0" ;
constant s_gt42 : bit_vector (6 downto 0) := B"100010_0" ;
constant s_gt46 : bit_vector (6 downto 0) := B"100110_0" ;
constant s_gt47 : bit_vector (6 downto 0) := B"100111_0" ;
constant s_gt55 : bit_vector (6 downto 0) := B"101101_0" ;
constant s_gt56 : bit_vector (6 downto 0) := B"101110_0" ;
constant s_gt60 : bit_vector (6 downto 0) := B"110000_0" ;

begin

	-- ###--------------------------------------------------------###
	-- #   checking power supplies					#
	-- ###--------------------------------------------------------###

power : assert ((VDD and VDDP) = '1' and (VSS or VSSP) = '0')
        report  "power supply missing on `dlx_m` processor"
        severity WARNING;

	-- ###--------------------------------------------------------###
	-- #   internal clocks						#
	-- ###--------------------------------------------------------###

CKFRZ_S  <= CK and not FRZ;
CK_S     <= CK            ;
CKDLY0_S <= CK            ;
CKDLY1_S <= CKDLY0_S      ;
CKDLY2_S <= CKDLY1_S      ;
CKDLY3_S <= CKDLY2_S      ;
CKDLY4_S <= CKDLY3_S      ;
CKDLY5_S <= CKDLY4_S      ;
CKDLY6_S <= CKDLY5_S      ;

	-- ###--------------------------------------------------------###
	-- #   hardware interrupt requests				#
	-- #     - interrupt request					#
	-- #     - exception request					#
	-- #     - global interrupt request signal			#
	-- ###--------------------------------------------------------###

INTRQS_X <= (IT_R (0) or IT_R (1) or IT_R (2) or IT_R (3)) and SR_R (1);

EXCRQS_X <= OVRFLO_X or             OVR_R or
            DAALGN_X or DASGMT_X or DAV_R or
            OPVIOL_X or ILLINS_X or ICO_R or
            IAALGN_X or IASGMT_X or IAV_R ;

RQS_X   <= INTRQS_X or EXCRQS_X or RESET_R;

	-- ###--------------------------------------------------------###
	-- #   extract control fields from the micro-instruction	#
	-- # register							#
	-- ###--------------------------------------------------------###

CTLOPX_S <= MICINS_R (25 downto 22);
CTLOPY_S <= MICINS_R (21 downto 19);
CTLALU_S <= MICINS_R (18 downto 15);
CTLRES_S <= MICINS_R (14 downto 11);
CTLRW_S  <= MICINS_R (10 downto  7);
CTLSEQ_S <= MICINS_R ( 6 downto  0);

	-- ###--------------------------------------------------------###
	-- #   extract the operation code from the instruction		#
	-- ###--------------------------------------------------------###

OPCOD_S  <= IR_R (31 downto 26) ;

	-- ###--------------------------------------------------------###
	-- #   detect unknown operation codes and privileged		#
	-- # instructions						#
	-- ###--------------------------------------------------------###

with OPCOD_S select
UNKOPC_X <= '0' when add_i  | sub_i  |
                     addi_i | subi_i |
                     sll_i  | srl_i  | sra_i    |
                     slli_i | srli_i | srai_i   | lhi_i    |
                     seq_i  | sne_i  | sge_i    | sle_i    |
                     seqi_i | snei_i | sgei_i   | slei_i   |
                     sgt_i  | slt_i  |
                     sgti_i | slti_i |
                     and_i  | or_i   | xor_i    |
                     andi_i | ori_i  | xori_i   |
                     sw_i   | sb_i   | lbu_i    |
                     lw_i   |
                     jr_i   | jalr_i | movs2i_i | movi2s_i |
                     beqz_i | bnez_i |
                     j_i    | jal_i  | rfe_i    | trap_i   ,
            '1' when others;

with OPCOD_S select
PRVINS_X <= '1' when rfe_i | movi2s_i | movs2i_i ,
            '0' when others                      ;

	-- ###--------------------------------------------------------###
	-- #   compute next micro-instruction's address			#
	-- ###--------------------------------------------------------###

MICADR_S (5 downto 4) <= CTLSEQ_S (6 downto 5) ;

MICADR_S (3 downto 0) <= CTLSEQ_S (4 downto 1) when CTLSEQ_S (0) = '0' else
                         B"000" & RQS_X        when CTLSEQ_S = s_next  else
                         B"000" & not RESNUL_S when CTLSEQ_S = s_nnul  else
                         B"000" &     RESNUL_S when CTLSEQ_S = s_nul   else
                         B"01"  & IR_R    (1 downto 0)
                                               when CTLSEQ_S = s_i2s   else
                         B"11"  & IR_R    (1 downto 0)
                                               when CTLSEQ_S = s_s2i   else
                         B"1"   & OPCOD_S (2 downto 0)
                                               when CTLSEQ_S = s_mem   else
                         cop2                  when CTLSEQ_S = s_cod2  else
                         cop1                  when CTLSEQ_S = s_cod1  else
                         "0000"                ;

with (OPCOD_S (5) & OPCOD_S (1)) select
cop2 <= not OPCOD_S (4 downto 3) & OPCOD_S (1 downto 0) when "10",
            OPCOD_S (4 downto 3) & OPCOD_S (1 downto 0) when others;

with OPCOD_S select
cop1 <= B"0100" when add_i    | sub_i  |
                     sll_i    | srl_i  | sra_i  |
                     seq_i    | sne_i  | sge_i  | sle_i  |
                     sgt_i    | slt_i  |
                     and_i    | or_i   | xor_i           ,
        B"0101" when addi_i   | subi_i |
                     slli_i   | srli_i | srai_i | lhi_i  |
                     seqi_i   | snei_i | sgei_i | slei_i |
                     sgti_i   | slti_i                   ,
        B"0110" when andi_i   | ori_i  | xori_i          ,
        B"0000" when sw_i     | sb_i   | lbu_i  | lw_i   ,
        B"0010" when beqz_i                              ,
        B"0011" when bnez_i                              ,
        B"1000" when jr_i                                ,
        B"1001" when jalr_i                              ,
        B"1010" when movs2i_i                            ,
        B"1011" when movi2s_i                            ,
        B"1100" when j_i                                 ,
        B"1101" when jal_i                               ,
        B"1110" when rfe_i                               ,
        B"1111" when trap_i                              ,
        B"0000" when others                              ;

	-- ###--------------------------------------------------------###
	-- #   read the next micro-instruction from the control store	#
	-- ###--------------------------------------------------------###

with MICADR_S (5 downto 0) select
MICINS_S <=
  x_rs  & y_i16 & a_sum  & r_ad   & m_no   & s_mem  when O"00" ,--adr
  x_rs  & y_c0  & a_sum  & r_no   & m_no   & s_nul  when O"02" ,--beqz
  x_rs  & y_c0  & a_sum  & r_no   & m_no   & s_nnul when O"03" ,--bnez
  x_rt  & y_c0  & a_sum  & r_ad   & m_no   & s_cod2 when O"04" ,--reg
  x_c0  & y_i16 & a_sum  & r_ad   & m_no   & s_cod2 when O"05" ,--imd
  x_ch  & y_i16 & a_and  & r_ad   & m_no   & s_cod2 when O"06" ,--imdu
  x_rs  & y_c0  & a_sum  & r_pc   & m_no   & s_gt60 when O"10" ,--jr
  x_pc  & y_c0  & a_sum  & r_r31  & m_no   & s_gt10 when O"11" ,--jalr
  x_c0  & y_c0  & a_sum  & r_no   & m_no   & s_s2i  when O"12" ,--s2i
  x_c0  & y_c0  & a_sum  & r_no   & m_no   & s_i2s  when O"13" ,--i2s
  x_pc  & y_i28 & a_sum  & r_pc   & m_no   & s_gt60 when O"14" ,--j
  x_pc  & y_c0  & a_sum  & r_r31  & m_no   & s_gt14 when O"15" ,--jal
  x_iar & y_c0  & a_sum  & r_pc   & m_no   & s_gt42 when O"16" ,--rfe
  x_c0  & y_i28 & a_sum  & r_tvr  & m_no   & s_gt41 when O"17" ,--trap
  x_rs  & y_ad  & a_sumv & r_rd   & m_ftch & s_next when O"20" ,--add
  x_rs  & y_ad  & a_difv & r_rd   & m_ftch & s_next when O"22" ,--sub
  x_rs  & y_ad  & a_xor  & r_rd   & m_ftch & s_next when O"23" ,--lxor
  x_rs  & y_ad  & a_sll  & r_rd   & m_ftch & s_next when O"24" ,--sll
  x_rs  & y_ad  & a_srl  & r_rd   & m_ftch & s_next when O"25" ,--srl
  x_rs  & y_ad  & a_sra  & r_rd   & m_ftch & s_next when O"26" ,--sra
  x_ad  & y_c16 & a_sll  & r_rd   & m_ftch & s_next when O"27" ,--lhi
  x_rs  & y_ad  & a_seq  & r_rd   & m_ftch & s_next when O"30" ,--seq
  x_rs  & y_ad  & a_sne  & r_rd   & m_ftch & s_next when O"31" ,--sne
  x_rs  & y_ad  & a_sge  & r_rd   & m_ftch & s_next when O"32" ,--sge
  x_rs  & y_ad  & a_sle  & r_rd   & m_ftch & s_next when O"33" ,--sle
  x_rs  & y_ad  & a_and  & r_rd   & m_ftch & s_next when O"34" ,--land
  x_rs  & y_ad  & a_or   & r_rd   & m_ftch & s_next when O"35" ,--lor
  x_rs  & y_ad  & a_sgt  & r_rd   & m_ftch & s_next when O"36" ,--sgt
  x_rs  & y_ad  & a_slt  & r_rd   & m_ftch & s_next when O"37" ,--slt
  x_pc  & y_c4  & a_sum  & r_pc   & m_no   & s_cod1 when O"40" ,--init
  x_pc  & y_c0  & a_sum  & r_siar & m_no   & s_gt47 when O"41" ,--irq
  x_sr  & y_c16 & a_srl  & r_sr   & m_no   & s_gt60 when O"42" ,--sr16r
  x_c0  & y_c16 & a_dif  & r_pc   & m_no   & s_gt60 when O"46" ,--pct
  x_sr  & y_c16 & a_sll  & r_ssr  & m_no   & s_gt46 when O"47" ,--sr16l
  x_rt  & y_c0  & a_sum  & r_no   & m_ww   & s_gt60 when O"50" ,--sw
  x_rt  & y_c0  & a_sum  & r_no   & m_wb   & s_gt60 when O"52" ,--sb
  x_c0  & y_c0  & a_sum  & r_no   & m_rb   & s_gt56 when O"53" ,--lbu
  x_c0  & y_c0  & a_sum  & r_no   & m_rw   & s_gt55 when O"54" ,--lw
  x_c0  & y_dt  & a_sum  & r_rd   & m_ftch & s_next when O"55" ,--lw2
  x_cb  & y_dt  & a_and  & r_rd   & m_ftch & s_next when O"56" ,--lbu2
  x_c0  & y_c0  & a_sum  & r_no   & m_ftch & s_next when O"60",--ifetch
  x_pc  & y_i18 & a_sum  & r_pc   & m_no   & s_gt60 when O"61",--branch
  x_rs  & y_c0  & a_sum  & r_tvr  & m_ftch & s_next when O"64" ,--i2tvr
  x_rs  & y_c0  & a_sum  & r_iar  & m_ftch & s_next when O"65" ,--i2iar
  x_rs  & y_c0  & a_sum  & r_sr   & m_ftch & s_next when O"66" ,--i2sr
  x_tvr & y_c0  & a_sum  & r_rd   & m_ftch & s_next when O"74" ,--tvr2i
  x_iar & y_c0  & a_sum  & r_rd   & m_ftch & s_next when O"75" ,--iar2i
  x_sr  & y_c0  & a_sum  & r_rd   & m_ftch & s_next when O"76" ,--sr2i
  x_c0  & y_c0  & a_sum  & r_no   & m_no   & s_gt41 when others;

	-- ###--------------------------------------------------------###
	-- #   define micro-instruction's value in case of reset	#
	-- ###--------------------------------------------------------###

RESTMI_X <= x_c0 & y_c0 & a_sum & r_no & m_ftch & s_next ;

	-- ###--------------------------------------------------------###
	-- #   assign micro-instruction and micro-instruction's address	#
	-- # registers							#
	-- ###--------------------------------------------------------###

mic_ins : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE)
begin
 MICADR_R <= guarded MICADR_S;
 MICINS_R <= guarded MICINS_S when (RESET = '0') else
                     RESTMI_X                        ;
end block ;

	-- ###--------------------------------------------------------###
	-- #   extract the immediate from in the instruction register	#
	-- #								#
	-- #     imd16 : 16-bit immediate with sign extension		#
	-- #     imd18 : 16-bit short branch offset with sign extension	#
	-- #     imd28 : 26-bit long  branch offset with sign extension	#
	-- ###--------------------------------------------------------###

IMD16_S (15 downto  0) <= IR_R (15 downto 0) ;
IMD16_S (31 downto 16) <= X"ffff" when (IR_R (15) = '1') else
                          X"0000" ;

IMD18_S (17 downto  0) <= IR_R (15 downto 0) & B"00";
IMD18_S (31 downto 18) <= X"fff" & B"11" when (IR_R (15) = '1') else
                          X"000" & B"00" ;

IMD28_S (27 downto  0) <= IR_R (25 downto 0) & B"00";
IMD28_S (31 downto 28) <= X"f" when (IR_R (25) = '1') else
                          X"0" ;

	-- ###--------------------------------------------------------###
	-- #   i format instructions					#
	-- ###--------------------------------------------------------###

with OPCOD_S select
IFORMT_S <= '1' when addi_i | subi_i |
                     slli_i | srli_i | srai_i   | lhi_i    |
                     seqi_i | snei_i | sgei_i   | slei_i   |
                     sgti_i | slti_i |
                     andi_i | ori_i  | xori_i   |
                     sw_i   | sb_i   | lbu_i    |
                     lw_i   |
                     beqz_i | bnez_i                       ,
            '0' when others                                ;

	-- ###--------------------------------------------------------###
	-- #   read and write pointers from register file		#
	-- ###--------------------------------------------------------###

WRTPNT_S <= B"11111"            when (CTLRES_S = r_r31) else
            IR_R (20 downto 16) when (IFORMT_S = '1'  ) else
            IR_R (15 downto 11) ;

with CTLOPX_S select
REDPNT_S <= IR_R (25 downto 21) when x_rs  ,
            IR_R (20 downto 16) when others;

	-- ###--------------------------------------------------------###
	-- #   register read from the register file			#
	-- ###--------------------------------------------------------###

with REDPNT_S select
REDREG_S <= R0_R  when B"00000" ,
            R1_R  when B"00001" ,
            R2_R  when B"00010" ,
            R3_R  when B"00011" ,
            R4_R  when B"00100" ,
            R5_R  when B"00101" ,
            R6_R  when B"00110" ,
            R7_R  when B"00111" ,
            R8_R  when B"01000" ,
            R9_R  when B"01001" ,
            R10_R when B"01010" ,
            R11_R when B"01011" ,
            R12_R when B"01100" ,
            R13_R when B"01101" ,
            R14_R when B"01110" ,
            R15_R when B"01111" ,
            R16_R when B"10000" ,
            R17_R when B"10001" ,
            R18_R when B"10010" ,
            R19_R when B"10011" ,
            R20_R when B"10100" ,
            R21_R when B"10101" ,
            R22_R when B"10110" ,
            R23_R when B"10111" ,
            R24_R when B"11000" ,
            R25_R when B"11001" ,
            R26_R when B"11010" ,
            R27_R when B"11011" ,
            R28_R when B"11100" ,
            R29_R when B"11101" ,
            R30_R when B"11110" ,
            R31_R when B"11111" ;

	-- ###--------------------------------------------------------###
	-- #   x and y operands						#
	-- ###--------------------------------------------------------###

with CTLOPX_S select
OPERX_S <= REDREG_S when x_rs   ,
           REDREG_S when x_rt   ,
           PC_R     when x_pc   ,
           AD_R     when x_ad   ,
           SR_R     when x_sr   ,
           IAR_R    when x_iar  ,
           TVR_R    when x_tvr  ,
           c0       when x_c0   ,
           cb       when x_cb   ,
           ch       when x_ch   ,
           c0       when others ;

with CTLOPY_S select
OPERY_S <= IMD16_S when y_i16  ,
           IMD18_S when y_i18  ,
           IMD28_S when y_i28  ,
           DT_R    when y_dt   ,
           AD_R    when y_ad   ,
           c0      when y_c0   ,
           c4      when y_c4   ,
           c16     when y_c16  ,
           c0      when others ;

	-- ###--------------------------------------------------------###
	-- #   adder's x and y operands					#
	-- ###--------------------------------------------------------###

ADDX_S <= OPERX_S;

with CTLALU_S select
ADDY_S (31 downto 0) <=      OPERY_S  when a_sum | a_sumv,
                        not (OPERY_S) when others;

	-- ###--------------------------------------------------------###
	-- #   adder's carry and result					#
	-- ###--------------------------------------------------------###

with CTLALU_S select
ADDCRY_S (0) <= '0'  when a_sum | a_sumv,
                '1'  when others;

ADDCRY_S (32 downto 1) <= (ADDX_S and ADDY_S                ) or
                          (ADDX_S and ADDCRY_S (31 downto 0)) or
                          (ADDY_S and ADDCRY_S (31 downto 0)) ;

ADDRES_S <=  ADDX_S xor ADDY_S xor ADDCRY_S (31 downto 0);

	-- ###--------------------------------------------------------###
	-- #   adder's overflow						#
	-- ###--------------------------------------------------------###

ADDOVR_S <= ADDCRY_S (32) xor ADDCRY_S (31);

	-- ###--------------------------------------------------------###
	-- #   test and set bits :					#
	-- #     seq : x  = y						#
	-- ###--------------------------------------------------------###

  SEQ_S <= '1' when (ADDRES_S = X"00000000") else
           '0' ;

  SGT_S <= '1' when ((OPERX_S (31) xor OPERY_S (31) ='0') and
                     (ADDRES_S (31) = '0') and (SEQ_S = '0')) else
         '1' when (OPERX_S (31) = '0' and OPERY_S (31) = '1')  else
         '0' ;

  SNE_S <= not (SEQ_S) ;
  SGE_S <=      SEQ_S or SGT_S;
  SLE_S <=      SEQ_S or SLT_S;
  SLT_S <= not (SGE_S);

	-- ###--------------------------------------------------------###
	-- #   shifter							#
	-- ###--------------------------------------------------------###

  SHIN_S   <= X"00000000" when CTLALU_S     = a_srl else	-- logical
              X"ffffffff" when OPERX_S (31) = '1'   else	-- arithm.
              X"00000000" ;					-- arithm.

  with OPERY_S (4 downto 0) select
  SHLFT_S <= OPERX_S (31 downto 0)                     when B"00000" ,
             OPERX_S (30 downto 0) & c0 (31)           when B"00001" ,
             OPERX_S (29 downto 0) & c0 (31 downto 30) when B"00010" ,
             OPERX_S (28 downto 0) & c0 (31 downto 29) when B"00011" ,
             OPERX_S (27 downto 0) & c0 (31 downto 28) when B"00100" ,
             OPERX_S (26 downto 0) & c0 (31 downto 27) when B"00101" ,
             OPERX_S (25 downto 0) & c0 (31 downto 26) when B"00110" ,
             OPERX_S (24 downto 0) & c0 (31 downto 25) when B"00111" ,
             OPERX_S (23 downto 0) & c0 (31 downto 24) when B"01000" ,
             OPERX_S (22 downto 0) & c0 (31 downto 23) when B"01001" ,
             OPERX_S (21 downto 0) & c0 (31 downto 22) when B"01010" ,
             OPERX_S (20 downto 0) & c0 (31 downto 21) when B"01011" ,
             OPERX_S (19 downto 0) & c0 (31 downto 20) when B"01100" ,
             OPERX_S (18 downto 0) & c0 (31 downto 19) when B"01101" ,
             OPERX_S (17 downto 0) & c0 (31 downto 18) when B"01110" ,
             OPERX_S (16 downto 0) & c0 (31 downto 17) when B"01111" ,
             OPERX_S (15 downto 0) & c0 (31 downto 16) when B"10000" ,
             OPERX_S (14 downto 0) & c0 (31 downto 15) when B"10001" ,
             OPERX_S (13 downto 0) & c0 (31 downto 14) when B"10010" ,
             OPERX_S (12 downto 0) & c0 (31 downto 13) when B"10011" ,
             OPERX_S (11 downto 0) & c0 (31 downto 12) when B"10100" ,
             OPERX_S (10 downto 0) & c0 (31 downto 11) when B"10101" ,
             OPERX_S (9  downto 0) & c0 (31 downto 10) when B"10110" ,
             OPERX_S (8  downto 0) & c0 (31 downto  9) when B"10111" ,
             OPERX_S (7  downto 0) & c0 (31 downto  8) when B"11000" ,
             OPERX_S (6  downto 0) & c0 (31 downto  7) when B"11001" ,
             OPERX_S (5  downto 0) & c0 (31 downto  6) when B"11010" ,
             OPERX_S (4  downto 0) & c0 (31 downto  5) when B"11011" ,
             OPERX_S (3  downto 0) & c0 (31 downto  4) when B"11100" ,
             OPERX_S (2  downto 0) & c0 (31 downto  3) when B"11101" ,
             OPERX_S (1  downto 0) & c0 (31 downto  2) when B"11110" ,
             OPERX_S (0)           & c0 (31 downto  1) when B"11111" ;

  with OPERY_S (4 downto 0) select
  SHRIT_S <=                        OPERX_S (31 downto  0) when B"00000" ,
             SHIN_S ( 0         ) & OPERX_S (31 downto  1) when B"00001" ,
             SHIN_S ( 1 downto 0) & OPERX_S (31 downto  2) when B"00010" ,
             SHIN_S ( 2 downto 0) & OPERX_S (31 downto  3) when B"00011" ,
             SHIN_S ( 3 downto 0) & OPERX_S (31 downto  4) when B"00100" ,
             SHIN_S ( 4 downto 0) & OPERX_S (31 downto  5) when B"00101" ,
             SHIN_S ( 5 downto 0) & OPERX_S (31 downto  6) when B"00110" ,
             SHIN_S ( 6 downto 0) & OPERX_S (31 downto  7) when B"00111" ,
             SHIN_S ( 7 downto 0) & OPERX_S (31 downto  8) when B"01000" ,
             SHIN_S ( 8 downto 0) & OPERX_S (31 downto  9) when B"01001" ,
             SHIN_S ( 9 downto 0) & OPERX_S (31 downto 10) when B"01010" ,
             SHIN_S (10 downto 0) & OPERX_S (31 downto 11) when B"01011" ,
             SHIN_S (11 downto 0) & OPERX_S (31 downto 12) when B"01100" ,
             SHIN_S (12 downto 0) & OPERX_S (31 downto 13) when B"01101" ,
             SHIN_S (13 downto 0) & OPERX_S (31 downto 14) when B"01110" ,
             SHIN_S (14 downto 0) & OPERX_S (31 downto 15) when B"01111" ,
             SHIN_S (15 downto 0) & OPERX_S (31 downto 16) when B"10000" ,
             SHIN_S (16 downto 0) & OPERX_S (31 downto 17) when B"10001" ,
             SHIN_S (17 downto 0) & OPERX_S (31 downto 18) when B"10010" ,
             SHIN_S (18 downto 0) & OPERX_S (31 downto 19) when B"10011" ,
             SHIN_S (19 downto 0) & OPERX_S (31 downto 20) when B"10100" ,
             SHIN_S (20 downto 0) & OPERX_S (31 downto 21) when B"10101" ,
             SHIN_S (21 downto 0) & OPERX_S (31 downto 22) when B"10110" ,
             SHIN_S (22 downto 0) & OPERX_S (31 downto 23) when B"10111" ,
             SHIN_S (23 downto 0) & OPERX_S (31 downto 24) when B"11000" ,
             SHIN_S (24 downto 0) & OPERX_S (31 downto 25) when B"11001" ,
             SHIN_S (25 downto 0) & OPERX_S (31 downto 26) when B"11010" ,
             SHIN_S (26 downto 0) & OPERX_S (31 downto 27) when B"11011" ,
             SHIN_S (27 downto 0) & OPERX_S (31 downto 28) when B"11100" ,
             SHIN_S (28 downto 0) & OPERX_S (31 downto 29) when B"11101" ,
             SHIN_S (29 downto 0) & OPERX_S (31 downto 30) when B"11110" ,
             SHIN_S (30 downto 0) & OPERX_S (31)           when B"11111" ;

	-- ###--------------------------------------------------------###
	-- #   result out of alu					#
	-- ###--------------------------------------------------------###

  with CTLALU_S select
  RESULT_S <= ADDRES_S                  when a_sum | a_sumv,
              ADDRES_S                  when a_dif | a_difv,
              OPERX_S and OPERY_S       when a_and         ,
              OPERX_S or  OPERY_S       when a_or          ,
              OPERX_S xor OPERY_S       when a_xor         ,
              SHLFT_S                   when a_sll         ,
              SHRIT_S                   when a_srl         ,
              SHRIT_S                   when a_sra         ,
              c0 (31 downto 1) & SEQ_S  when a_seq         ,
              c0 (31 downto 1) & SNE_S  when a_sne         ,
              c0 (31 downto 1) & SGE_S  when a_sge         ,
              c0 (31 downto 1) & SGT_S  when a_sgt         ,
              c0 (31 downto 1) & SLE_S  when a_sle         ,
              c0 (31 downto 1) & SLT_S  when a_slt         ,
              c0                        when others        ;

	-- ###--------------------------------------------------------###
	-- #   checking the result out of alu				#
	-- ###--------------------------------------------------------###

RESNUL_S <= '1' when (RESULT_S = X"00000000") else
            '0' ;

	-- ###--------------------------------------------------------###
	-- #   external storage access :				#
	-- #     - access type (word, byte)				#
	-- #     - valid bytes						#
	-- ###--------------------------------------------------------###

WORD_S <= '1' when (CTLRW_S = m_ftch or CTLRW_S = m_rw or CTLRW_S = m_ww) else
          '0' ;

BYTE_S <= '1' when (CTLRW_S = m_rb   or CTLRW_S = m_wb                  ) else
          '0' ;

BYTSEL_S <= "1111" when (WORD_S = '1'                             ) else
            "0001" when (BYTE_S = '1' and AD_R (1 downto 0) = "11") else
            "0010" when (BYTE_S = '1' and AD_R (1 downto 0) = "10") else
            "0100" when (BYTE_S = '1' and AD_R (1 downto 0) = "01") else
            "1000" when (BYTE_S = '1' and AD_R (1 downto 0) = "00") else
            "0000" ;

	-- ###--------------------------------------------------------###
	-- #   data from external storage read and aligned		#
	-- ###--------------------------------------------------------###

REDDAT_S (31 downto 8) <= DATA (31 downto  8) ;
REDDAT_S ( 7 downto 0) <= DATA ( 7 downto  0) when (BYTSEL_S (3) = '1') else
                          DATA (15 downto  8) when (BYTSEL_S (2) = '1') else
                          DATA (23 downto 16) when (BYTSEL_S (1) = '1') else
                          DATA (31 downto 24) ;

	-- ###--------------------------------------------------------###
	-- #   prepare the new status to be written into the 16 least	#
	-- # significant bits of sr in case of interruption or exception#
	-- ###--------------------------------------------------------###

NEWSR_X <= IT_R & OVR_R & DAV_R & ICO_R & IAV_R & "0000" & RESET_R & "000";

	-- ###--------------------------------------------------------###
	-- #   registers' write enable					#
	-- ###--------------------------------------------------------###

with CTLRES_S select
WENSR_S  <= not EXCRQS_X when r_sr  ,
            '1'          when r_ssr ,
            '0'          when others;

with CTLRES_S select
WENIAR_S <= not EXCRQS_X when r_iar ,
            '1'          when r_siar,
            '0'          when others;

WENTVR_S <= not EXCRQS_X when (CTLRES_S = r_tvr                   ) else
            '0'          ;
WENPC_S  <= not EXCRQS_X when (CTLRES_S = r_pc                    ) else
            '0'          ;
WENAD_S  <= not EXCRQS_X when (CTLRES_S = r_ad                    ) else
            '0'          ;
WENREG_S <= not EXCRQS_X when (CTLRES_S = r_rd or CTLRES_S = r_r31) else
            '0'          ;
WENDT_S  <= not EXCRQS_X when (CTLRW_S = m_rw   or CTLRW_S = m_rb ) else
            '0'          ;
WENIR_S  <= not EXCRQS_X when (CTLRW_S = m_ftch                   ) else
            '0'          ;

	-- ###--------------------------------------------------------###
	-- #   write the result into registers :			#
	-- #     sr  : status register					#
	-- #     iar : interrupt address register			#
	-- #     tvr : trap vector register				#
	-- #     pc  : program counter					#
	-- #     ad  : internal address register			#
	-- ###--------------------------------------------------------###

status : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE and WENSR_S = '1')
begin
  SR_R <= guarded RESULT_S (31 downto  0)           when CTLRES_S = r_sr else
                  RESULT_S (31 downto 16) & NEWSR_X;
end block;

it_adr : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE and WENIAR_S = '1')
begin
  IAR_R <= guarded RESULT_S;
end block;

trap_v : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE and WENTVR_S = '1')
begin
  TVR_R <= guarded RESULT_S;
end block;

prg_cnt : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE and WENPC_S = '1')
begin
  PC_R <= guarded RESULT_S;
end block;

address : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE and WENAD_S = '1')
begin
  AD_R <= guarded RESULT_S;
end block;

	-- ###--------------------------------------------------------###
	-- #   write the value read on data bus into registers :	#
	-- #     dt  : data register					#
	-- #     ir  : instruction register				#
	-- ###--------------------------------------------------------###

data_in : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE and WENDT_S = '1')
begin
  DT_R <= guarded REDDAT_S;
end block ;

instruc : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE and WENIR_S = '1')
begin
  IR_R  <= guarded REDDAT_S;
end block ;

	-- ###--------------------------------------------------------###
	-- #   write integre registers					#
	-- ###--------------------------------------------------------###

r1  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "00001" and
             WENREG_S = '1')
begin
  R1_R  <= guarded RESULT_S;
end block;

r2  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "00010" and
             WENREG_S = '1')
begin
  R2_R  <= guarded RESULT_S;
end block;

r3  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "00011" and
             WENREG_S = '1')
begin
  R3_R  <= guarded RESULT_S;
end block;

r4  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "00100" and
             WENREG_S = '1')
begin
  R4_R  <= guarded RESULT_S;
end block;

r5  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "00101" and
             WENREG_S = '1')
begin
  R5_R  <= guarded RESULT_S;
end block;

r6  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "00110" and
             WENREG_S = '1')
begin
  R6_R  <= guarded RESULT_S;
end block;

r7  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "00111" and
             WENREG_S = '1')
begin
  R7_R  <= guarded RESULT_S;
end block;

r8  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "01000" and
             WENREG_S = '1')
begin
  R8_R  <= guarded RESULT_S;
end block;

r9  : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "01001" and
             WENREG_S = '1')
begin
  R9_R  <= guarded RESULT_S;
end block;

r10 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "01010" and
             WENREG_S = '1')
begin
  R10_R <= guarded RESULT_S;
end block;

r11 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "01011" and
             WENREG_S = '1')
begin
  R11_R <= guarded RESULT_S;
end block;

r12 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "01100" and
             WENREG_S = '1')
begin
  R12_R <= guarded RESULT_S;
end block;

r13 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "01101" and
             WENREG_S = '1')
begin
  R13_R <= guarded RESULT_S;
end block;

r14 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "01110" and
             WENREG_S = '1')
begin
  R14_R <= guarded RESULT_S;
end block;

r15 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "01111" and
             WENREG_S = '1')
begin
  R15_R <= guarded RESULT_S;
end block;

r16 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "10000" and
             WENREG_S = '1')
begin
  R16_R <= guarded RESULT_S;
end block;

r17 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "10001" and
             WENREG_S = '1')
begin
  R17_R <= guarded RESULT_S;
end block;

r18 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "10010" and
             WENREG_S = '1')
begin
  R18_R <= guarded RESULT_S;
end block;

r19 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "10011" and
             WENREG_S = '1')
begin
  R19_R <= guarded RESULT_S;
end block;

r20 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "10100" and
             WENREG_S = '1')
begin
  R20_R <= guarded RESULT_S;
end block;

r21 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "10101" and
             WENREG_S = '1')
begin
  R21_R <= guarded RESULT_S;
end block;

r22 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "10110" and
             WENREG_S = '1')
begin
  R22_R <= guarded RESULT_S;
end block;

r23 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "10111" and
             WENREG_S = '1')
begin
  R23_R <= guarded RESULT_S;
end block;

r24 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "11000" and
             WENREG_S = '1')
begin
  R24_R <= guarded RESULT_S;
end block;

r25 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "11001" and
             WENREG_S = '1')
begin
  R25_R <= guarded RESULT_S;
end block;

r26 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "11010" and
             WENREG_S = '1')
begin
  R26_R <= guarded RESULT_S;
end block;

r27 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "11011" and
             WENREG_S = '1')
begin
  R27_R <= guarded RESULT_S;
end block;

r28 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "11100" and
             WENREG_S = '1')
begin
  R28_R <= guarded RESULT_S;
end block;

r29 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "11101" and
             WENREG_S = '1')
begin
  R29_R <= guarded RESULT_S;
end block;

r30 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "11110" and
             WENREG_S = '1')
begin
  R30_R <= guarded RESULT_S ;
end block;

r31 : block (CKFRZ_S  = '0' and not CKFRZ_S'STABLE and WRTPNT_S = "11111" and
             WENREG_S = '1')
begin
  R31_R <= guarded RESULT_S;
end block;

	-- ###--------------------------------------------------------###
	-- #   exceptions						#
	-- ###--------------------------------------------------------###

with CTLALU_S select
OVRFLO_X <= ADDOVR_S when a_sumv | a_difv ,
            '0'      when others          ;

ILLINS_X <= UNKOPC_X when (CTLSEQ_S = s_cod1) else
            '0';

OPVIOL_X <= SR_R (0) and PRVINS_X when (CTLSEQ_S = s_cod1) else
            '0'                   ;

IAALGN_X <= PC_R (1) or PC_R (0) when (CTLRW_S = m_ftch) else
            '0'                  ;

IASGMT_X <= PC_R (31) and SR_R (0) when (CTLRW_S = m_ftch) else
            '0'                    ;

with CTLRW_S select
DAALGN_X <= AD_R (1) or AD_R (0) when m_ww  | m_rw,
            '0'                  when others;

with CTLRW_S select
DASGMT_X <= AD_R (31) and SR_R (0) when m_ww  | m_wb | m_rw | m_rb,
            '0'                    when others;

	-- ###--------------------------------------------------------###
	-- #   assign exception registers				#
	-- ###--------------------------------------------------------###

except : block (CKFRZ_S = '0' and not CKFRZ_S'STABLE)
begin
  OVR_R <= guarded OVRFLO_X                      when (CTLRES_S = r_ssr) else
                   OVRFLO_X or OVR_R             ;

  DAV_R <= guarded DAALGN_X or DASGMT_X          when (CTLRES_S = r_ssr) else
                   DAALGN_X or DASGMT_X or DAV_R ;

  ICO_R <= guarded OPVIOL_X or ILLINS_X          when (CTLRES_S = r_ssr) else
                   OPVIOL_X or ILLINS_X or ICO_R ;

  IAV_R <= guarded IAALGN_X or IASGMT_X          when (CTLRES_S = r_ssr) else
                   IAALGN_X or IASGMT_X or IAV_R ;
end block;

	-- ###--------------------------------------------------------###
	-- #   assign registers (those independent from the execution	#
	-- # of an instruction)						#
	-- ###--------------------------------------------------------###

ext_it : block (CK_S = '0' and not CK_S'STABLE)
begin
  FRZ_R   <= guarded FRZ              ;
  RESET_R <= guarded RESET            when (CTLRES_S = r_ssr) else
                     RESET or RESET_R ;
  IT_R    <= guarded not IT           when (CTLRES_S = r_ssr) else
                     not IT or IT_R   ;
end block;

	-- ###--------------------------------------------------------###
	-- #   assign outputs :						#
	-- #     - desable write accesses on exception			#
	-- #     - enable output tristate buffers of data bus only on	#
	-- #       high level of (delayed) ck to avoid conflicts	#
	-- #     - enable output tristate buffers only if the chip is	#
	-- #       not freezed						#
	-- #     - align datas before writing on data bus		#
	-- ### ------------------------------------------------------ ###

data : block ( CKDLY6_S = '1'  and (FRZ and FRZ_R) = '0' and
              (CTLRW_S  = m_ww  or  CTLRW_S        = m_wb))
begin
  with CTLRW_S select
  DATA <= guarded RESULT_S                                        when m_ww,
                  RESULT_S (7 downto 0) & RESULT_S (7 downto 0) &
                  RESULT_S (7 downto 0) & RESULT_S (7 downto 0)   when others;
end block ;

adr : block ((FRZ and FRZ_R) = '0')
begin
  with CTLRW_S select
  ADR <= guarded AD_R when m_ww | m_wb | m_rw | m_rb,
                 PC_R when others;
end block;

SCOUT <= '0';

BYTE  <= BYTSEL_S when (EXCRQS_X = '0') else
         "0000"   ;

RW    <= '0' when (CTLRW_S = m_ww or CTLRW_S = m_wb) else
         '1' ;


end BEHAVIOURAL;
