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

📄 pm_fetch_dec.vhd

📁 AVR IP core writen in VHDL. It is beta version, working even with AVR studio
💻 VHD
📖 第 1 页 / 共 5 页
字号:
	   idc_lds or                                                     -- LDS instruction(two cycle execution)
	   idc_pop or                                                     -- POP instruction
       idc_ret or 	                                                -- RET instruction 
	   idc_reti)='1') 												    -- RETI instruction 
	   then ramre_int <='1';
    end if;
   when '1' =>	
    if ((ld_st or lds_st or pop_st or ret_st2 or reti_st2)and not cpuwait)='1' then 
     ramre_int <='0';
    end if;
   when others  =>	null;
  end case;
 end if;  
end if;
end process;			 
			 
-- ramwe LOGIC (16 BIT ADDRESS ramadr[15..0] FOR DATA RAM (64*1024-64-32 LOCATIONS))
--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 -- ST/STD/STS/PUSH/RCALL
--			                                icall_st1 or icall_st2 or -- ICALL
--			                                call_st2 or call_st3 or   -- CALL
--											irq_st2 or irq_st3);      -- INTERRUPT

DataMemoryWrite:process(cp2,ireset)
begin
if ireset='0' then -- Reset
 ramwe_int <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
 if (cp2en='1') then 							  -- Clock enable
  case ramwe_int is
   when '0' =>	
    if(ramadr_reg_in(15 downto 5)/=const_ram_to_io_a and 
	   ramadr_reg_in(15 downto 5)/=const_ram_to_io_b and   
       ramadr_reg_in(15 downto 5)/=const_ram_to_reg  and  
      (idc_st_x or idc_st_y or idc_std_y or idc_st_z or idc_std_z or  -- ST/STD instruction	
	   idc_sts or                                                     -- STS instruction (two cycle execution)	
	   idc_push or                                                    -- PUSH instruction
	   idc_rcall or													  -- RCALL instruction
	   idc_icall or													  -- ICALL instruction
	   call_st1 or                                                    -- CALL instruction
	   irq_st1)='1')                                                  -- Interrupt  
	  then ramwe_int <='1';
    end if;
   when '1' =>	
    if ((st_st or sts_st or push_st or rcall_st2 or 
	     icall_st2 or call_st3 or irq_st3)and not cpuwait)='1' then ramwe_int <='0';
    end if;
   when others  =>	null;
  end case;
end if;
end if;
end process;

-- DBUSOUT MULTIPLEXER
dbusout_mux_logic: for i in dbusout_int'range generate
dbusout_int(i)<= (reg_rd_out(i) and (idc_push or idc_sts 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_st))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;


-- gp_reg_tmp STORES TEMPREOARY THE VALUE OF SOURCE REGISTER DURING ST/STD/STS INSTRUCTION
gp_registers_trig:process(cp2,ireset)
begin
if (ireset='0') then
gp_reg_tmp <= (others=>'0');
elsif (cp2='1' and cp2'event) then
 if (cp2en='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 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 if;
end process;

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

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

program_counter_high_store:process(cp2,ireset)
begin
if ireset='0' then                         -- RESET
program_counter_high_fr <=(others => '0');
elsif (cp2='1' and cp2'event) then       -- CLOCK
 if (cp2en='1') then 							  -- Clock enable
  if (idc_rcall or idc_icall or call_st1 or irq_st1) ='1' then   
   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 if;
end process;


program_counter_for_lpm_elpm:process(cp2,ireset)
begin
if ireset='0' then                         -- RESET
program_counter_tmp<=(others => '0');
elsif (cp2='1' and cp2'event) then       -- CLOCK
 if (cp2en='1') then 							  -- Clock enable
  if (idc_lpm or idc_elpm) ='1' then       
   program_counter_tmp <= program_counter;               
  end if;
 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       -- +
              "11111"&dex_adr12mem_s(10 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_st or lds_st) and cpuwait)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_st or lds_st) and cpuwait) 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(cp2,ireset)
begin
if ireset='0' then                              -- RESET
pc_low<=(others => '0');
elsif (cp2='1' and cp2'event) then              -- CLOCK
 if (cp2en='1') then 							-- Clock enable
  if pc_low_en ='1' then                          
   pc_low <= program_counter_in(7 downto 0);
  end if;
 end if;
end if;
end process;

program_counter_high:process(cp2,ireset)
begin
if ireset='0' then                               -- RESET
pc_high<=(others => '0');
elsif (cp2='1' and cp2'event) then               -- CLOCK
 if (cp2en='1') then 							 -- Clock enable
  if pc_high_en ='1' then                          
   pc_high <= program_counter_in(15 downto 8);
  end if;
 end if;
end if;
end process;

pc <= program_counter;														   


program_counter_for_interrupt:process(cp2,ireset)
begin
if ireset='0' then                                 -- RESET
pc_for_interrupt <=(others => '0');
elsif (cp2='1' and cp2'event) then               -- CLOCK
 if (cp2en='1') then 							 -- Clock enable
  if irq_start ='1' then                           
   pc_for_interrupt <= program_counter;
  end if;
 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(cp2,ireset)
begin
if ireset='0' then                       -- RESET
nskip_inst_st0 <= '0';
skip_inst_st1  <= '0';
skip_inst_st2  <= '0';
elsif (cp2='1' and cp2'event) then       -- CLOCK
 if (cp2en='1') then 				     -- Clock enable
  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 if;
end process;



alu_state_machines:process(cp2,ireset)
begin
if ireset='0' then                       -- RESET
adiw_st <= '0';
sbiw_st <= '0';
elsif (cp2='1' and cp2'event) then       -- CLOCK
 if (cp2en='1') then 					 -- Clock enable
  adiw_st <= not adiw_st and idc_adiw;
  sbiw_st <= not sbiw_st and idc_sbiw;
 end if;
end if;
end process;


lpm_state_machine:process(cp2,ireset)
begin
if ireset='0' then                       -- RESET
nlpm_st0 <= '0';
lpm_st1 <= '0';
lpm_st2 <= '0';
elsif (cp2='1' and cp2'event) then       -- CLOCK
 if (cp2en='1') then 							  -- Clock enable
  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 if;
end process;


lds_state_machine:process(cp2,ireset)
begin
if ireset='0' then                       -- RESET
 lds_st <= '0';
elsif (cp2='1' and cp2'event) then       -- CLOCK
 if (cp2en='1') then 							  -- Clock enable	
  lds_st  <= (not lds_st and idc_lds) or (lds_st and cpuwait);
 end if;
end if;
end process;


sts_state_machine:process(cp2,ireset)
begin
if ireset='0' then                       -- RESET
 sts_st <= '0';
elsif (cp2='1' and cp2'event) then       -- CLOCK
 if (cp2en='1') then 							  -- Clock enable

⌨️ 快捷键说明

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