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

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_decode.vhd] - Diff between revs 9 and 12

Only display areas with differences | Details | Blame | View Log

Rev 9 Rev 12
---------------------------------------------------------------------
---------------------------------------------------------------------
-- Instruction decoder
-- Instruction decoder
--
--
-- Part of the LXP32 CPU
-- Part of the LXP32 CPU
--
--
-- Copyright (c) 2016 by Alex I. Kuznetsov
-- Copyright (c) 2016 by Alex I. Kuznetsov
--
--
-- The second stage of the LXP32 pipeline.
-- The second stage of the LXP32 pipeline.
---------------------------------------------------------------------
---------------------------------------------------------------------
 
 
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_std.all;
 
 
entity lxp32_decode is
entity lxp32_decode is
        port(
        port(
                clk_i: in std_logic;
                clk_i: in std_logic;
                rst_i: in std_logic;
                rst_i: in std_logic;
 
 
                word_i: in std_logic_vector(31 downto 0);
                word_i: in std_logic_vector(31 downto 0);
                next_ip_i: in std_logic_vector(29 downto 0);
                next_ip_i: in std_logic_vector(29 downto 0);
                current_ip_i: in std_logic_vector(29 downto 0);
                current_ip_i: in std_logic_vector(29 downto 0);
                valid_i: in std_logic;
                valid_i: in std_logic;
                jump_valid_i: in std_logic;
                jump_valid_i: in std_logic;
                ready_o: out std_logic;
                ready_o: out std_logic;
 
 
                interrupt_valid_i: in std_logic;
                interrupt_valid_i: in std_logic;
                interrupt_vector_i: in std_logic_vector(2 downto 0);
                interrupt_vector_i: in std_logic_vector(2 downto 0);
                interrupt_ready_o: out std_logic;
                interrupt_ready_o: out std_logic;
 
 
 
                wakeup_i: in std_logic;
 
 
                sp_raddr1_o: out std_logic_vector(7 downto 0);
                sp_raddr1_o: out std_logic_vector(7 downto 0);
                sp_rdata1_i: in std_logic_vector(31 downto 0);
                sp_rdata1_i: in std_logic_vector(31 downto 0);
                sp_raddr2_o: out std_logic_vector(7 downto 0);
                sp_raddr2_o: out std_logic_vector(7 downto 0);
                sp_rdata2_i: in std_logic_vector(31 downto 0);
                sp_rdata2_i: in std_logic_vector(31 downto 0);
 
 
                ready_i: in std_logic;
                ready_i: in std_logic;
                valid_o: out std_logic;
                valid_o: out std_logic;
 
 
                cmd_loadop3_o: out std_logic;
                cmd_loadop3_o: out std_logic;
                cmd_signed_o: out std_logic;
                cmd_signed_o: out std_logic;
                cmd_dbus_o: out std_logic;
                cmd_dbus_o: out std_logic;
                cmd_dbus_store_o: out std_logic;
                cmd_dbus_store_o: out std_logic;
                cmd_dbus_byte_o: out std_logic;
                cmd_dbus_byte_o: out std_logic;
                cmd_addsub_o: out std_logic;
                cmd_addsub_o: out std_logic;
                cmd_mul_o: out std_logic;
                cmd_mul_o: out std_logic;
                cmd_div_o: out std_logic;
                cmd_div_o: out std_logic;
                cmd_div_mod_o: out std_logic;
                cmd_div_mod_o: out std_logic;
                cmd_cmp_o: out std_logic;
                cmd_cmp_o: out std_logic;
                cmd_jump_o: out std_logic;
                cmd_jump_o: out std_logic;
                cmd_negate_op2_o: out std_logic;
                cmd_negate_op2_o: out std_logic;
                cmd_and_o: out std_logic;
                cmd_and_o: out std_logic;
                cmd_xor_o: out std_logic;
                cmd_xor_o: out std_logic;
                cmd_shift_o: out std_logic;
                cmd_shift_o: out std_logic;
                cmd_shift_right_o: out std_logic;
                cmd_shift_right_o: out std_logic;
 
 
                jump_type_o: out std_logic_vector(3 downto 0);
                jump_type_o: out std_logic_vector(3 downto 0);
 
 
                op1_o: out std_logic_vector(31 downto 0);
                op1_o: out std_logic_vector(31 downto 0);
                op2_o: out std_logic_vector(31 downto 0);
                op2_o: out std_logic_vector(31 downto 0);
                op3_o: out std_logic_vector(31 downto 0);
                op3_o: out std_logic_vector(31 downto 0);
                dst_o: out std_logic_vector(7 downto 0)
                dst_o: out std_logic_vector(7 downto 0)
        );
        );
end entity;
end entity;
 
 
architecture rtl of lxp32_decode is
architecture rtl of lxp32_decode is
 
 
-- Decoder FSM state
-- Decoder FSM state
 
 
type DecoderState is (Regular,ContinueLc,ContinueCjmp,ContinueInterrupt,Halt);
type DecoderState is (Regular,ContinueLc,ContinueCjmp,ContinueInterrupt,Halt);
signal state: DecoderState:=Regular;
signal state: DecoderState:=Regular;
 
 
-- Input instruction portions
-- Input instruction portions
 
 
signal opcode: std_logic_vector(5 downto 0);
signal opcode: std_logic_vector(5 downto 0);
signal t1: std_logic;
signal t1: std_logic;
signal t2: std_logic;
signal t2: std_logic;
signal destination: std_logic_vector(7 downto 0);
signal destination: std_logic_vector(7 downto 0);
signal rd1: std_logic_vector(7 downto 0);
signal rd1: std_logic_vector(7 downto 0);
signal rd2: std_logic_vector(7 downto 0);
signal rd2: std_logic_vector(7 downto 0);
 
 
-- Signals related to pipeline control
-- Signals related to pipeline control
 
 
signal downstream_busy: std_logic;
signal downstream_busy: std_logic;
signal self_busy: std_logic:='0';
signal self_busy: std_logic:='0';
signal busy: std_logic;
signal busy: std_logic;
signal valid_out: std_logic:='0';
signal valid_out: std_logic:='0';
 
 
signal dst_out: std_logic_vector(7 downto 0);
signal dst_out: std_logic_vector(7 downto 0);
 
 
-- Signals related to RD operand decoding
-- Signals related to RD operand decoding
 
 
signal rd1_reg: std_logic_vector(7 downto 0);
signal rd1_reg: std_logic_vector(7 downto 0);
signal rd2_reg: std_logic_vector(7 downto 0);
signal rd2_reg: std_logic_vector(7 downto 0);
 
 
signal rd1_select: std_logic;
signal rd1_select: std_logic;
signal rd1_direct: std_logic_vector(31 downto 0);
signal rd1_direct: std_logic_vector(31 downto 0);
signal rd2_select: std_logic;
signal rd2_select: std_logic;
signal rd2_direct: std_logic_vector(31 downto 0);
signal rd2_direct: std_logic_vector(31 downto 0);
 
 
-- Signals related to interrupt handling
-- Signals related to interrupt handling
 
 
signal interrupt_ready: std_logic:='0';
signal interrupt_ready: std_logic:='0';
 
signal wakeup_reg: std_logic:='0';
 
 
begin
begin
 
 
-- Dissect input word
-- Dissect input word
 
 
opcode<=word_i(31 downto 26);
opcode<=word_i(31 downto 26);
t1<=word_i(25);
t1<=word_i(25);
t2<=word_i(24);
t2<=word_i(24);
destination<=word_i(23 downto 16);
destination<=word_i(23 downto 16);
rd1<=word_i(15 downto 8);
rd1<=word_i(15 downto 8);
rd2<=word_i(7 downto 0);
rd2<=word_i(7 downto 0);
 
 
-- Pipeline control
-- Pipeline control
 
 
downstream_busy<=valid_out and not ready_i;
downstream_busy<=valid_out and not ready_i;
busy<=downstream_busy or self_busy;
busy<=downstream_busy or self_busy;
 
 
process (clk_i) is
process (clk_i) is
begin
begin
        if rising_edge(clk_i) then
        if rising_edge(clk_i) then
                if rst_i='1' then
                if rst_i='1' then
                        valid_out<='0';
                        valid_out<='0';
                        self_busy<='0';
                        self_busy<='0';
                        state<=Regular;
                        state<=Regular;
                        interrupt_ready<='0';
                        interrupt_ready<='0';
                        cmd_loadop3_o<='-';
                        cmd_loadop3_o<='-';
                        cmd_signed_o<='-';
                        cmd_signed_o<='-';
                        cmd_dbus_o<='-';
                        cmd_dbus_o<='-';
                        cmd_dbus_store_o<='-';
                        cmd_dbus_store_o<='-';
                        cmd_dbus_byte_o<='-';
                        cmd_dbus_byte_o<='-';
                        cmd_addsub_o<='-';
                        cmd_addsub_o<='-';
                        cmd_negate_op2_o<='-';
                        cmd_negate_op2_o<='-';
                        cmd_mul_o<='-';
                        cmd_mul_o<='-';
                        cmd_div_o<='-';
                        cmd_div_o<='-';
                        cmd_div_mod_o<='-';
                        cmd_div_mod_o<='-';
                        cmd_cmp_o<='-';
                        cmd_cmp_o<='-';
                        cmd_jump_o<='-';
                        cmd_jump_o<='-';
                        cmd_and_o<='-';
                        cmd_and_o<='-';
                        cmd_xor_o<='-';
                        cmd_xor_o<='-';
                        cmd_shift_o<='-';
                        cmd_shift_o<='-';
                        cmd_shift_right_o<='-';
                        cmd_shift_right_o<='-';
                        rd1_select<='-';
                        rd1_select<='-';
                        rd1_direct<=(others=>'-');
                        rd1_direct<=(others=>'-');
                        rd2_select<='-';
                        rd2_select<='-';
                        rd2_direct<=(others=>'-');
                        rd2_direct<=(others=>'-');
                        op3_o<=(others=>'-');
                        op3_o<=(others=>'-');
                        jump_type_o<=(others=>'-');
                        jump_type_o<=(others=>'-');
                        dst_out<=(others=>'-');
                        dst_out<=(others=>'-');
 
                        wakeup_reg<='0';
                else
                else
                        interrupt_ready<='0';
                        interrupt_ready<='0';
 
                        wakeup_reg<=wakeup_reg or wakeup_i;
                        if jump_valid_i='1' then
                        if jump_valid_i='1' then
                                valid_out<='0';
                                valid_out<='0';
                                self_busy<='0';
                                self_busy<='0';
                                state<=Regular;
                                state<=Regular;
                        elsif downstream_busy='0' then
                        elsif downstream_busy='0' then
                                op3_o<=(others=>'-');
                                op3_o<=(others=>'-');
                                rd1_direct<=std_logic_vector(resize(signed(rd1),rd1_direct'length));
                                rd1_direct<=std_logic_vector(resize(signed(rd1),rd1_direct'length));
                                rd2_direct<=std_logic_vector(resize(signed(rd2),rd2_direct'length));
                                rd2_direct<=std_logic_vector(resize(signed(rd2),rd2_direct'length));
 
 
                                cmd_signed_o<=opcode(0);
                                cmd_signed_o<=opcode(0);
                                cmd_div_mod_o<=opcode(1);
                                cmd_div_mod_o<=opcode(1);
                                cmd_shift_right_o<=opcode(1);
                                cmd_shift_right_o<=opcode(1);
                                cmd_dbus_byte_o<=opcode(1);
                                cmd_dbus_byte_o<=opcode(1);
                                cmd_dbus_store_o<=opcode(2);
                                cmd_dbus_store_o<=opcode(2);
 
 
                                case state is
                                case state is
                                when Regular =>
                                when Regular =>
                                        cmd_loadop3_o<='0';
                                        cmd_loadop3_o<='0';
                                        cmd_dbus_o<='0';
                                        cmd_dbus_o<='0';
                                        cmd_addsub_o<='0';
                                        cmd_addsub_o<='0';
                                        cmd_negate_op2_o<='0';
                                        cmd_negate_op2_o<='0';
                                        cmd_mul_o<='0';
                                        cmd_mul_o<='0';
                                        cmd_div_o<='0';
                                        cmd_div_o<='0';
                                        cmd_cmp_o<='0';
                                        cmd_cmp_o<='0';
                                        cmd_jump_o<='0';
                                        cmd_jump_o<='0';
                                        cmd_and_o<='0';
                                        cmd_and_o<='0';
                                        cmd_xor_o<='0';
                                        cmd_xor_o<='0';
                                        cmd_shift_o<='0';
                                        cmd_shift_o<='0';
 
 
                                        jump_type_o<=opcode(3 downto 0);
                                        jump_type_o<=opcode(3 downto 0);
 
 
                                        if interrupt_valid_i='1' and valid_i='1' then
                                        if interrupt_valid_i='1' and valid_i='1' then
                                                cmd_jump_o<='1';
                                                cmd_jump_o<='1';
                                                cmd_loadop3_o<='1';
                                                cmd_loadop3_o<='1';
                                                op3_o<=current_ip_i&"01"; -- LSB indicates interrupt return
                                                op3_o<=current_ip_i&"01"; -- LSB indicates interrupt return
                                                dst_out<=X"FD"; -- interrupt return pointer
                                                dst_out<=X"FD"; -- interrupt return pointer
                                                rd1_select<='1';
                                                rd1_select<='1';
                                                rd2_select<='0';
                                                rd2_select<='0';
                                                valid_out<='1';
                                                valid_out<='1';
                                                interrupt_ready<='1';
                                                interrupt_ready<='1';
                                                self_busy<='1';
                                                self_busy<='1';
                                                state<=ContinueInterrupt;
                                                state<=ContinueInterrupt;
                                        else
                                        else
                                                if opcode(5 downto 3)="101" or opcode="000001" then -- lc or lcs
                                                if opcode(5 downto 3)="101" or opcode="000001" then -- lc or lcs
                                                        cmd_loadop3_o<='1';
                                                        cmd_loadop3_o<='1';
-- Setting op3_o here only affects the lcs instruction
-- Setting op3_o here only affects the lcs instruction
                                                        op3_o<=std_logic_vector(resize(signed(opcode(2 downto 0)&
                                                        op3_o<=std_logic_vector(resize(signed(opcode(2 downto 0)&
                                                                t1&t2&rd1&rd2),op3_o'length));
                                                                t1&t2&rd1&rd2),op3_o'length));
                                                end if;
                                                end if;
 
 
                                                if opcode(5 downto 3)="001" then
                                                if opcode(5 downto 3)="001" then
                                                        cmd_dbus_o<='1';
                                                        cmd_dbus_o<='1';
                                                end if;
                                                end if;
 
 
                                                if opcode(5 downto 1)="01000" then
                                                if opcode(5 downto 1)="01000" then
                                                        cmd_addsub_o<='1';
                                                        cmd_addsub_o<='1';
                                                end if;
                                                end if;
 
 
                                                cmd_negate_op2_o<=opcode(0);
                                                cmd_negate_op2_o<=opcode(0);
 
 
                                                if opcode="010010" then
                                                if opcode="010010" then
                                                        cmd_mul_o<='1';
                                                        cmd_mul_o<='1';
                                                end if;
                                                end if;
 
 
                                                if opcode(5 downto 2)="0101" then
                                                if opcode(5 downto 2)="0101" then
                                                        cmd_div_o<='1';
                                                        cmd_div_o<='1';
                                                end if;
                                                end if;
 
 
                                                if opcode(5 downto 3)="100" then -- jump or call
                                                if opcode(5 downto 3)="100" then -- jump or call
                                                        cmd_jump_o<='1';
                                                        cmd_jump_o<='1';
                                                        cmd_loadop3_o<=opcode(0);
                                                        cmd_loadop3_o<=opcode(0);
-- Setting op3_o here only affects the call instruction
-- Setting op3_o here only affects the call instruction
                                                        op3_o<=next_ip_i&"00";
                                                        op3_o<=next_ip_i&"00";
                                                end if;
                                                end if;
 
 
                                                -- Note: (a or b) = (a and b) or (a xor b)
                                                -- Note: (a or b) = (a and b) or (a xor b)
 
 
                                                if opcode(5 downto 1)="01100" then
                                                if opcode(5 downto 1)="01100" then
                                                        cmd_and_o<='1';
                                                        cmd_and_o<='1';
                                                end if;
                                                end if;
 
 
                                                if opcode="011010" or opcode="011001" then
                                                if opcode="011010" or opcode="011001" then
                                                        cmd_xor_o<='1';
                                                        cmd_xor_o<='1';
                                                end if;
                                                end if;
 
 
                                                if opcode(5 downto 2)="0111" then
                                                if opcode(5 downto 2)="0111" then
                                                        cmd_shift_o<='1';
                                                        cmd_shift_o<='1';
                                                end if;
                                                end if;
 
 
                                                if opcode(5 downto 4)="11" then
                                                if opcode(5 downto 4)="11" then
                                                        cmd_cmp_o<='1';
                                                        cmd_cmp_o<='1';
                                                        cmd_negate_op2_o<='1';
                                                        cmd_negate_op2_o<='1';
                                                end if;
                                                end if;
 
 
                                                rd1_select<=t1;
                                                rd1_select<=t1;
                                                rd2_select<=t2;
                                                rd2_select<=t2;
 
 
                                                dst_out<=destination;
                                                dst_out<=destination;
 
 
                                                if valid_i='1' then
                                                if valid_i='1' then
                                                        if opcode="000001" then
                                                        if opcode="000001" then
                                                                valid_out<='0';
                                                                valid_out<='0';
                                                                self_busy<='0';
                                                                self_busy<='0';
                                                                state<=ContinueLc;
                                                                state<=ContinueLc;
                                                        elsif opcode="000010" then
                                                        elsif opcode="000010" then
                                                                valid_out<='0';
                                                                valid_out<='0';
                                                                self_busy<='1';
                                                                self_busy<='1';
 
                                                                wakeup_reg<='0';
                                                                state<=Halt;
                                                                state<=Halt;
                                                        elsif opcode(5 downto 4)="11" then
                                                        elsif opcode(5 downto 4)="11" then
                                                                valid_out<='1';
                                                                valid_out<='1';
                                                                self_busy<='1';
                                                                self_busy<='1';
                                                                state<=ContinueCjmp;
                                                                state<=ContinueCjmp;
                                                        else
                                                        else
                                                                valid_out<='1';
                                                                valid_out<='1';
                                                        end if;
                                                        end if;
                                                else
                                                else
                                                        valid_out<='0';
                                                        valid_out<='0';
                                                end if;
                                                end if;
                                        end if;
                                        end if;
                                when ContinueLc =>
                                when ContinueLc =>
                                        if valid_i='1' then
                                        if valid_i='1' then
                                                valid_out<='1';
                                                valid_out<='1';
                                                op3_o<=word_i;
                                                op3_o<=word_i;
                                                self_busy<='0';
                                                self_busy<='0';
                                                state<=Regular;
                                                state<=Regular;
                                        end if;
                                        end if;
                                when ContinueCjmp =>
                                when ContinueCjmp =>
                                        valid_out<='1';
                                        valid_out<='1';
                                        cmd_jump_o<='1';
                                        cmd_jump_o<='1';
                                        rd1_select<='1';
                                        rd1_select<='1';
                                        self_busy<='0';
                                        self_busy<='0';
                                        state<=Regular;
                                        state<=Regular;
                                when ContinueInterrupt =>
                                when ContinueInterrupt =>
                                        valid_out<='0';
                                        valid_out<='0';
                                when Halt =>
                                when Halt =>
                                        if interrupt_valid_i='1' then
                                        if interrupt_valid_i='1' or wakeup_i='1' or wakeup_reg='1' then
                                                self_busy<='0';
                                                self_busy<='0';
                                                state<=Regular;
                                                state<=Regular;
                                        end if;
                                        end if;
                                end case;
                                end case;
                        end if;
                        end if;
                end if;
                end if;
        end if;
        end if;
end process;
end process;
 
 
valid_o<=valid_out;
valid_o<=valid_out;
dst_o<=dst_out;
dst_o<=dst_out;
 
 
ready_o<=not busy;
ready_o<=not busy;
 
 
interrupt_ready_o<=interrupt_ready;
interrupt_ready_o<=interrupt_ready;
 
 
-- Decode RD (register/direct) operands
-- Decode RD (register/direct) operands
 
 
process (clk_i) is
process (clk_i) is
begin
begin
        if rising_edge(clk_i) then
        if rising_edge(clk_i) then
                if busy='0' then
                if busy='0' then
                        rd1_reg<=rd1;
                        rd1_reg<=rd1;
                        rd2_reg<=rd2;
                        rd2_reg<=rd2;
                end if;
                end if;
        end if;
        end if;
end process;
end process;
 
 
sp_raddr1_o<="11110"&interrupt_vector_i when (state=Regular and interrupt_valid_i='1' and downstream_busy='0') or state=ContinueInterrupt else
sp_raddr1_o<="11110"&interrupt_vector_i when (state=Regular and interrupt_valid_i='1' and downstream_busy='0') or state=ContinueInterrupt else
        dst_out when (state=ContinueCjmp and downstream_busy='0') else
        dst_out when (state=ContinueCjmp and downstream_busy='0') else
        rd1_reg when busy='1' else
        rd1_reg when busy='1' else
        rd1;
        rd1;
 
 
sp_raddr2_o<=rd2_reg when busy='1' else rd2;
sp_raddr2_o<=rd2_reg when busy='1' else rd2;
 
 
op1_o<=sp_rdata1_i when rd1_select='1' else rd1_direct;
op1_o<=sp_rdata1_i when rd1_select='1' else rd1_direct;
op2_o<=sp_rdata2_i when rd2_select='1' else rd2_direct;
op2_o<=sp_rdata2_i when rd2_select='1' else rd2_direct;
 
 
end architecture;
end architecture;
 
 

powered by: WebSVN 2.1.0

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