📄 control_mem.vhd
字号:
-- activities triggered by rising edge of clock
elsif clk'event and clk = '1' then
intblock_o <= s_intblock;
for i in 0 to C_IMPL_N_EXT-1 loop
s_int0_h1(i) <= int0_i(i); -- external INT0
s_int0_h2(i) <= s_int0_h1(i);
s_int0_h3(i) <= s_int0_h2(i);
s_int1_h1(i) <= int1_i(i); -- external INT1
s_int1_h2(i) <= s_int1_h1(i);
s_int1_h3(i) <= s_int1_h2(i);
end loop;
for i in 0 to C_IMPL_N_TMR-1 loop
s_tf0_h1(i) <= all_tf0_i(i); -- TF0 flags
s_tf0_h2(i) <= s_tf0_h1(i);
s_tf1_h1(i) <= all_tf1_i(i); -- TF1 flags
s_tf1_h2(i) <= s_tf1_h1(i);
-- all_xxx is a std_logic_vector, s_xxx is a array of std_logic !!!
end loop;
for i in 0 to C_IMPL_N_SIU-1 loop
s_ri_h1(i) <= all_scon_i(i*3); -- RI flag
s_ri_h2(i) <= s_ri_h1(i);
s_ti_h1(i) <= all_scon_i((i*3)+1); -- TI flag
s_ti_h2(i) <= s_ti_h1(i);
-- all_xxx is a std_logic_vector, s_xxx is a array of std_logic !!!
end loop;
end if;
end process iep;
------------------------------------------------------------------------------
-- purpose: check the interupt-sources and start an interupt if necessary
-- inputs: ie,ip,scon,tcon,s_inthigh,s_intlow,s_ti,s_ri,s_ie0,
-- s_ie1,s_tf0,s_tf1
-- outputs: s_intpre
------------------------------------------------------------------------------
intpre : process (ie,ip,scon,tcon,s_inthigh,s_intlow,s_ti,s_ri,s_ie0,
s_ie1,s_tf0,s_tf1)
begin
if (EA='1' and (EX0='1' or ET0='1' or EX1='1' or ET1='1' or ES='1')) then
if s_inthigh='1' then -- interrupt with high priority is running
s_intpre <= '0';
elsif s_intlow='1' then -- interrupt with low priority is running
if ((PX0 and EX0 and s_ie0) or
(PT0 and ET0 and s_tf0) or
(PX1 and EX1 and s_ie1) or
(PT1 and ET1 and s_tf1) or
(PS0 and ES and (s_ri or s_ti)))='1' then
s_intpre <= '1'; -- a second interrupt must start
else
s_intpre <= '0';
end if;
else -- no interrupt is running
if ((EX0 and s_ie0) or
(ET0 and s_tf0) or
(EX1 and s_ie1) or
(ET1 and s_tf1) or
(ES and (s_ri or s_ti)))='1' then
s_intpre <= '1'; -- an interrupt must start
else
s_intpre <= '0';
end if;
end if;
else -- no interrupt must be carry out
s_intpre <= '0';
end if;
end process intpre;
------------------------------------------------------------------------------
-- purpose: this are the main-multiplexer for reading and writing regs
-- inputs: s_data_mux,pc,aludata_i,s_reg_data,rom_data_i,acc,
-- s_bdata_mux,s_bit_data,psw,new_cy_i,s_helpb,sp,s_rr_adr,
-- s_ri_data,s_help,s_adr_mux,s_adr,s_regs_wr_en,pc_plus2,
-- s_help16,s_ri_adr,s_r0_b0,s_r1_b0,s_r0_b1,s_r1_b1,
-- s_r0_b2,s_r1_b2,s_r0_b3,s_r1_b3
-- outputs: s_data,s_bdata,s_adr,s_ri_data,ram_wr_o
------------------------------------------------------------------------------
p_multiplexer : process (s_data_mux,pc,aludata_i,s_reg_data,rom_data_i,acc,
s_bdata_mux,s_bit_data,psw,new_cy_i,s_helpb,sp,s_rr_adr,
s_ri_data,s_help,s_adr_mux,s_adr,s_regs_wr_en,pc_plus2,
s_help16,s_ri_adr,s_r0_b0,s_r1_b0,s_r0_b1,s_r1_b1,
s_r0_b2,s_r1_b2,s_r0_b3,s_r1_b3,s_adrx_mux,dph,dpl,
datax_i)
begin
case s_data_mux is
when "0000" => s_data <= conv_unsigned(0,8);
when "0001" => s_data <= pc(7 downto 0);
when "0010" => s_data <= pc(15 downto 8);
when "0011" => s_data <= unsigned(aludata_i);
when "0100" => s_data <= s_reg_data;
when "0101" => s_data <= unsigned(rom_data_i);
when "0110" => s_data <= acc;
when "0111" =>
s_data(7 downto 4) <= acc(3 downto 0);
s_data(3 downto 0) <= acc(7 downto 4);
when "1000" => s_data <= s_help;
when "1001" =>
s_data(7 downto 4) <= s_reg_data(7 downto 4);
s_data(3 downto 0) <= s_help(3 downto 0);
when "1010" =>
s_data(7 downto 4) <= acc(7 downto 4);
s_data(3 downto 0) <= s_reg_data(3 downto 0);
when "1100" => s_data <= s_help16(7 downto 0);
when "1101" => s_data <= s_help16(15 downto 8);
when "1110" => s_data <= pc_plus2(7 downto 0);
when "1111" => s_data <= unsigned(datax_i);
when others => s_data <= conv_unsigned(0,8);
end case;
case s_bdata_mux is
when "0000" => s_bdata <= '0';
when "0001" => s_bdata <= s_bit_data and cy;
when "0010" => s_bdata <= not(s_bit_data) and cy;
when "0011" => s_bdata <= new_cy_i(1);
when "0100" => s_bdata <= s_helpb;
when "0101" => s_bdata <= not cy;
when "0110" => s_bdata <= not s_bit_data;
when "0111" => s_bdata <= s_bit_data;
when "1000" => s_bdata <= cy;
when "1001" => s_bdata <= s_bit_data or cy;
when "1010" => s_bdata <= not(s_bit_data) or cy;
when "1011" => s_bdata <= '1';
when others => s_bdata <= '0';
end case;
case s_adr_mux is
when "0000" => s_adr <= conv_unsigned(0,8);
when "0001" => s_adr <= conv_unsigned(16#89#,8);
when "0010" => s_adr <= conv_unsigned(16#8D#,8);
when "0011" => s_adr <= conv_unsigned(16#8B#,8);
when "0100" => s_adr <= conv_unsigned(16#8F#,8);
when "0101" => s_adr <= sp;
when "0110" => s_adr <= s_rr_adr;
when "0111" => s_adr <= s_ri_data;
when "1000" => s_adr <= unsigned(rom_data_i);
when "1001" => s_adr <= s_reg_data;
when "1010" => s_adr <= s_help ;
when "1011" => s_adr <= conv_unsigned(16#D7#,8);
when "1100" => s_adr <= conv_unsigned(16#F0#,8);
when "1101" => s_adr <= conv_unsigned(16#82#,8);
when "1110" => s_adr <= conv_unsigned(16#83#,8);
when "1111" => s_adr <= sp + conv_unsigned(1,1);
when others => s_adr <= conv_unsigned(0,8);
end case;
case s_adrx_mux is
when "00" => adrx_o <= (others => '0');
when "01" =>
adrx_o(15 downto 8) <= std_logic_vector(dph);
adrx_o(7 downto 0) <= std_logic_vector(dpl);
when "10" =>
adrx_o(15 downto 8) <= (others => '0');
adrx_o(7 downto 0) <= std_logic_vector(s_ri_data);
when others => adrx_o <= (others => '0');
end case;
case s_ri_adr is
when "00000000" => s_ri_data <= s_r0_b0;
when "00000001" => s_ri_data <= s_r1_b0;
when "00001000" => s_ri_data <= s_r0_b1;
when "00001001" => s_ri_data <= s_r1_b1;
when "00010000" => s_ri_data <= s_r0_b2;
when "00010001" => s_ri_data <= s_r1_b2;
when "00011000" => s_ri_data <= s_r0_b3;
when "00011001" => s_ri_data <= s_r1_b3;
when others => s_ri_data <= conv_unsigned(0,8);
end case;
if ((s_regs_wr_en="100") or (s_regs_wr_en="101")) then -- write one byte
if ((s_adr(7)='1') or -- SFR
(conv_std_logic_vector(s_adr(7 downto 4),4)="0010") -- bitadressable
or ((std_logic_vector(s_adr) AND "11100110") = "00000000")) -- R0,R1
then
ram_wr_o <= '0';
else
ram_wr_o <= '1'; -- to RAM-block
end if;
else
ram_wr_o <= '0';
end if;
end process p_multiplexer;
------------------------------------------------------------------------------
-- purpose: writes internal registers, on which the user have no
-- direct access
-- inputs: reset,clk,s_nextstate,state,s_help_en,
-- rom_data_i,aludata_i,s_reg_data,s_rr_adr,new_cy_i
-- outputs: state,s_ir,s_help,s_help16,s_helpb,s_intpre2,s_intlow,
-- s_inthigh,s_preadr
------------------------------------------------------------------------------
p_wr_internal_reg : process (reset,clk)
begin
if reset='1' then
state <= STARTUP;
s_ir <= conv_unsigned(0,8);
s_help <= conv_unsigned(0,8);
s_help16 <= conv_unsigned(0,16);
s_helpb <= '0';
s_intpre2 <= '0';
s_intlow <= '0';
s_inthigh <= '0';
s_preadr <= conv_unsigned(0,8);
pc <= conv_unsigned(0,16);
s_p0 <= "11111111";
s_p1 <= "11111111";
s_p2 <= "11111111";
s_p3 <= "11111111";
s_ext0isr_d <= '0';
s_ext0isrh_d <= '0';
s_ext1isr_d <= '0';
s_ext1isrh_d <= '0';
else
if Rising_Edge(clk) then
state <= s_nextstate; -- update current state
if state=FETCH then
s_ir <= unsigned(rom_data_i); -- save OP-Code in IR
end if;
case s_help_en is
when "0000" => NULL;
when "0001" => s_help <= unsigned(rom_data_i);
when "0010" => s_help <= unsigned(aludata_i);
when "0011" => s_help <= s_reg_data;
when "0100" => s_help <= s_rr_adr;
when "0101" => s_help <= conv_unsigned(16#03#,8);
when "0110" => s_help <= conv_unsigned(16#0B#,8);
when "0111" => s_help <= conv_unsigned(16#13#,8);
when "1000" => s_help <= conv_unsigned(16#1B#,8);
when "1001" => s_help <= conv_unsigned(16#23#,8);
when "1010" => s_help <= acc;
when others => NULL;
end case;
case s_help16_en is
when "00" => NULL;
when "01" => s_help16 <= pc + conv_unsigned(3,2);
when "10" => s_help16 <= pc_plus2;
when "11" => s_help16 <= pc_plus1;
when others => NULL;
end case;
case s_helpb_en is
when '0' => NULL;
when '1' => s_helpb <= new_cy_i(1);
when others => NULL;
end case;
if s_intpre2_en='1' then -- help-reg for s_intpre
s_intpre2 <= s_intpre2_d;
else
NULL;
end if;
if s_intlow_en='1' then
s_intlow <= s_intlow_d;
else
NULL;
end if;
if s_inthigh_en='1' then
s_inthigh <= s_inthigh_d;
else
NULL;
end if;
if ext0isr_en_i = '1' then
s_ext0isr_d <= ext0isr_d_i;
end if;
if ext1isr_en_i = '1' then
s_ext1isr_d <= ext1isr_d_i;
end if;
if ext0isrh_en_i = '1' then
s_ext0isrh_d <= ext0isrh_d_i;
end if;
if ext1isrh_en_i = '1' then
s_ext1isrh_d <= ext1isrh_d_i;
end if;
s_preadr <= s_adr;
pc <= pc_comb; -- write pc-register
s_p0 <= p0_i;
s_p1 <= p1_i;
s_p2 <= p2_i;
s_p3 <= p3_i;
end if;
end if;
end process p_wr_internal_reg;
------------------------------------------------------------------------------
-- purpose: calculate the next PC-adress
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -