⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pm_fetch_dec.vhd

📁 avr core porocesssor vhdl source code
💻 VHD
📖 第 1 页 / 共 5 页
字号:
-- RAMRE/RAMWE LOGIC (16 BIT ADDRESS ramadr[15..0] FOR DATA RAM (64*1024-64-32 LOCATIONS))
ramre_int <= not(reg_file_adr_space or io_file_adr_space) and 
            (ld_st or lds_st2 or pop_st or
             ret_st1 or ret_st2 or reti_st1 or reti_st2);     -- LD/LDS/LDD/POP/RET/RETI

ramwe_int <= not(reg_file_adr_space or io_file_adr_space) and 
            (st_st or sts_st2 or push_st or rcall_st1 or rcall_st2 or 
			                                icall_st1 or icall_st2 or 
			                                call_st2 or call_st3 or 
											irq_st2 or irq_st3);   -- ST/STS/STD/PUSH/RCALL/CALL/ICALL + INTERRUPT
                                                       

-- DBUSOUT MULTIPLEXER
dbusout_mux_logic: for i in dbusout_int'range generate
dbusout_int(i)<= (reg_rd_out(i) and (idc_push or 
                 (idc_st_x or idc_st_y or idc_std_y or idc_st_z or idc_std_z)))or      -- PUSH/ST/STD/STS INSTRUCTIONS
				 (gp_reg_tmp(i) and (st_st or sts_st1 or sts_st2))or                            -- NEW
				 (bitpr_io_out(i) and (cbi_st or sbi_st))or                          -- CBI/SBI  INSTRUCTIONS
                 (program_counter(i)         and (idc_rcall or idc_icall or call_st1))or                        -- LOW  PART OF PC
                 (program_counter_high_fr(i) and (rcall_st1 or icall_st1 or call_st2))or                        -- HIGH PART OF PC
                 (pc_for_interrupt(i) and irq_st1) or
				 (pc_for_interrupt(i+8) and irq_st2) or
				 (reg_rd_out(i) and  idc_out); -- OUT
end generate;


-- ALU CONNECTION

-- ALU Rr INPUT MUX
alu_data_r_in <= dex_dat8_immed       when (idc_subi or idc_sbci or idc_andi or idc_ori or idc_cpi)='1' else
                 "00"&dex_dat6_immed  when (idc_adiw or idc_sbiw) ='1' else
                 "00000000"           when (adiw_st or sbiw_st) ='1' else
                 reg_rr_out;

-- ALU Rd INPUT
alu_data_d_in <= reg_rd_out;


-- gp_reg_tmp STORES TEMPREOARY THE VALUE OF SOURCE REGISTER DURING ST/STD/STS INSTRUCTION
gp_registers_trig:process(clk,nrst)
begin
if (nrst='0') then
gp_reg_tmp <= (others=>'0');
elsif (clk='1' and clk'event) then
-- if ((idc_st_x or idc_st_y or idc_std_y or idc_st_z or idc_std_z) or sts_st1)='1' then  -- CLOCK ENABLE
if ((idc_st_x or idc_st_y or idc_std_y or idc_st_z or idc_std_z) or idc_sts)='1' then  -- CLOCK ENABLE
gp_reg_tmp <= reg_rd_out;
end if;
end if;
end process;

-- **********************************************************************************************************

-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- +++++++++++++++++++++++++++++++++++++++ PROGRAM COUNTER ++++++++++++++++++++++++++++++++++++++++++++++++++
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

program_counter_high_store:process(clk,nrst)
begin
if nrst='0' then                         -- RESET
program_counter_high_fr <=(others => '0');
elsif (clk='1' and clk'event) then       -- CLOCK
if (idc_rcall or idc_icall or call_st1 or irq_st1) ='1' then   -- CLOCK ENABLE
program_counter_high_fr <= program_counter(15 downto 8);       -- STORE HIGH BYTE OF THE PROGRAMM COUNTER FOR RCALL/ICALL/CALL INSTRUCTIONS AND INTERRUPTS   
end if;
end if;
end process;


program_counter_for_lpm_elpm:process(clk,nrst)
begin
if nrst='0' then                         -- RESET
program_counter_tmp<=(others => '0');
elsif (clk='1' and clk'event) then       -- CLOCK
if (idc_lpm or idc_elpm) ='1' then       -- CLOCK ENABLE
program_counter_tmp <= program_counter;               
end if;
end if;
end process;

pa15_pm <= rampz_out(0) and idc_elpm; -- '0' WHEN LPM INSTRUCTIONS  RAMPZ(0) WHEN ELPM INSTRUCTION

-- OFFSET FOR BRBC/BRBS INSTRUCTIONS +63/-64
offset_brbx <= "0000000000"&dex_brxx_offset(5 downto 0) when (dex_brxx_offset(6)='0') else -- +
               "1111111111"&dex_brxx_offset(5 downto 0);                                   -- - 

-- OFFSET FOR RJMP/RCALL INSTRUCTIONS +2047/-2048
offset_rxx <= "00000"&dex_adr12mem_s(10 downto 0) when (dex_adr12mem_s(11)='0') else       -- +
              "1111111"&dex_adr12mem_s(8 downto 0);                                          -- -

program_counter <= pc_high&pc_low;

program_counter_in <= program_counter + offset_brbx when ((idc_brbc or idc_brbs) and  bit_test_op_out) ='1'else  -- BRBC/BRBS                  
                      program_counter + offset_rxx when (idc_rjmp or idc_rcall)='1'else     -- RJMP/RCALL
                      reg_z_out when (idc_ijmp or idc_icall)='1'else                        -- IJMP/ICALL
                      pa15_pm&reg_z_out(15 downto 1) when (idc_lpm or idc_elpm) ='1'else    -- LPM/ELPM
                      instruction_reg  when (jmp_st1 or call_st1)='1'else                    -- JMP/CALL
                      "0000000000"&irqackad_int&'0' when irq_st1 ='1' else                 -- INTERRUPT      
                      dbusin&"00000000"  when (ret_st1 or reti_st1)='1' else                 -- RET/RETI -> PC HIGH BYTE                  
                      "00000000"&dbusin  when (ret_st2 or reti_st2)='1' else                 -- RET/RETI -> PC LOW BYTE                       
                      program_counter_tmp when (lpm_st1)='1'                                 -- AFTER LPM/ELPM INSTRUCTION   
                      else program_counter+1;      -- THE MOST USUAL CASE

						  

pc_low_en  <= not (idc_ld_x or idc_ld_y or idc_ld_z or idc_ldd_y or idc_ldd_z or
	               idc_st_x or idc_st_y or idc_st_z or idc_std_y or idc_std_z or
				   sts_st1 or lds_st1 or 
				   idc_adiw or idc_sbiw or
				   idc_push or idc_pop or
				   idc_cbi or idc_sbi or
				   rcall_st1 or icall_st1 or call_st2 or irq_st2 or cpuwait or
				   ret_st1 or reti_st1); 


pc_high_en <= not (idc_ld_x or idc_ld_y or idc_ld_z or idc_ldd_y or idc_ldd_z or
	               idc_st_x or idc_st_y or idc_st_z or idc_std_y or idc_std_z or
				   sts_st1 or lds_st1 or 
				   idc_adiw or idc_sbiw or
				   idc_push or idc_pop or
				   idc_cbi or idc_sbi or
				   rcall_st1 or icall_st1 or call_st2 or irq_st2 or cpuwait or
				   ret_st2 or reti_st2);
				   
program_counter_low:process(clk,nrst)
begin
if nrst='0' then                                -- RESET
pc_low<=(others => '0');
elsif (clk='1' and clk'event) then              -- CLOCK
if pc_low_en ='1' then                          -- CLOCK ENABLE
pc_low <= program_counter_in(7 downto 0);
end if;
end if;
end process;

program_counter_high:process(clk,nrst)
begin
if nrst='0' then                                 -- RESET
pc_high<=(others => '0');
elsif (clk='1' and clk'event) then               -- CLOCK
if pc_high_en ='1' then                          -- CLOCK ENABLE
pc_high <= program_counter_in(15 downto 8);
end if;
end if;
end process;

pc <= program_counter;														   


program_counter_for_interrupt:process(clk,nrst)
begin
if nrst='0' then                                 -- RESET
pc_for_interrupt <=(others => '0');
elsif (clk='1' and clk'event) then               -- CLOCK
if irq_start ='1' then                           -- CLOCK ENABLE
pc_for_interrupt <= program_counter;
end if;
end if;
end process;

-- END OF PROGRAM COUNTER 

-- STATE MACHINES

skip_inst_start <= ((idc_sbrc or idc_sbrs or idc_sbic or idc_sbis) and bit_test_op_out)or
                   (idc_cpse and alu_z_flag_out);

skip_instruction_sm:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
nskip_inst_st0 <= '0';
skip_inst_st1  <= '0';
skip_inst_st2  <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
nskip_inst_st0 <= (not nskip_inst_st0 and skip_inst_start) or 
                  (nskip_inst_st0 and not((skip_inst_st1 and not two_word_inst) or skip_inst_st2));
skip_inst_st1  <= (not skip_inst_st1 and not nskip_inst_st0 and skip_inst_start);
skip_inst_st2  <=  not skip_inst_st2 and skip_inst_st1 and two_word_inst;
end if;
end process;



alu_state_machines:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
adiw_st <= '0';
sbiw_st <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
adiw_st <= not adiw_st and idc_adiw;
sbiw_st <= not sbiw_st and idc_sbiw;
end if;
end process;


lpm_state_machine:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
nlpm_st0 <= '0';
lpm_st1 <= '0';
lpm_st2 <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
nlpm_st0 <= (not nlpm_st0 and (idc_lpm or idc_elpm)) or (nlpm_st0 and not lpm_st2);
lpm_st1  <= (not lpm_st1 and not nlpm_st0 and (idc_lpm or idc_elpm)); -- ?? 
lpm_st2  <=  not lpm_st2 and lpm_st1;
end if;
end process;


lds_state_machine:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
nlds_st0 <= '0';
lds_st1 <= '0';
lds_st2 <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
nlds_st0 <= (not nlds_st0 and idc_lds) or (nlds_st0 and not (lds_st2 and not cpuwait));
lds_st1  <= not lds_st1 and not nlds_st0 and idc_lds;
lds_st2  <= (not lds_st2 and lds_st1) or (lds_st2 and cpuwait);
end if;
end process;


sts_state_machine:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
nsts_st0 <= '0';
sts_st1 <= '0';
sts_st2 <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
nsts_st0 <= (not nsts_st0 and idc_sts) or (nsts_st0 and not (sts_st2 and not cpuwait));
sts_st1  <=  not sts_st1 and not nsts_st0 and idc_sts;
sts_st2  <= (not sts_st2 and sts_st1) or (sts_st2 and cpuwait);
end if;
end process;

jmp_state_machine:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
njmp_st0 <= '0';
jmp_st1 <= '0';
jmp_st2 <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
njmp_st0 <= (not njmp_st0 and idc_jmp) or (njmp_st0 and not jmp_st2);
jmp_st1  <= not jmp_st1 and not njmp_st0 and idc_jmp; -- ?? 
jmp_st2  <= not jmp_st2 and jmp_st1;
end if;
end process;

rcall_state_machine:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
nrcall_st0 <= '0';
rcall_st1 <= '0';
rcall_st2 <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
nrcall_st0 <= (not nrcall_st0 and idc_rcall) or (nrcall_st0 and not (rcall_st2 and not cpuwait));
rcall_st1  <= (not rcall_st1 and not nrcall_st0 and idc_rcall) or (rcall_st1 and cpuwait);
rcall_st2  <= (not rcall_st2 and rcall_st1 and not cpuwait) or (rcall_st2 and cpuwait);
end if;
end process;

icall_state_machine:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
nicall_st0 <= '0';
icall_st1 <= '0';
icall_st2 <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
nicall_st0 <= (not nicall_st0 and idc_icall) or (nicall_st0 and not (icall_st2 and not cpuwait));
icall_st1  <= (not icall_st1 and not nicall_st0 and idc_icall) or (icall_st1 and cpuwait);
icall_st2  <= (not icall_st2 and icall_st1 and not cpuwait) or (icall_st2 and cpuwait);
end if;
end process;

call_state_machine:process(clk,nrst)
begin
if nrst='0' then                       -- RESET
ncall_st0 <= '0';
call_st1 <= '0';
call_st2 <= '0';
call_st3  <= '0';
elsif (clk='1' and clk'event) then       -- CLOCK
ncall_st0 <= (not ncall_st0 and idc_call) or (ncall_st0 and not( call_st3 and not cpuwait));
call_st1  <= not call_st1 and not ncall_st0 and idc_call;
call_st2  <= (not call_st2 and call_st1) or (call_st2 and cpuwait);
call_st3  <= (not call_st3 and call_st2 and not cpuwait) or (call_st3 and cpuwait);
end if;
end process;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -