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

📄 pm_fetch_dec.vhd

📁 一个FPGA的AVR_Core 仅供测试~
💻 VHD
📖 第 1 页 / 共 5 页
字号:
             reg_rr_out when (idc_mov='1')else                                     -- FOR MOV INSTRUCTION 
			 instruction_reg(15 downto 8) when (lpm_st2='1' and reg_z_out(0)='1') else -- LPM/ELPM
			 instruction_reg(7 downto 0) when  (lpm_st2='1' and reg_z_out(0)='0') else -- LPM/ELPM
             dex_dat8_immed when idc_ldi='1' else
			 alu_data_out;                                               -- FROM ALU DATA OUT

-- IORE/IOWE LOGIC (6 BIT ADDRESS adr[5..0] FOR I/O PORTS(64 LOCATIONS))
iore_int <= idc_in or idc_sbi or idc_cbi or idc_sbic or idc_sbis or ((ld_st or lds_st2) and io_file_adr_space);   -- IN/SBI/CBI 
iowe_int <= '1' when ((idc_out or sbi_st or cbi_st) or 
                     ((st_st or sts_st2) and io_file_adr_space))='1' else '0'; -- OUT/SBI/CBI + !! ST/STS/STD


-- adr[5..0] BUS MULTIPLEXER
adr_int <= dex_adr6port when (idc_in or idc_out) = '1' else                          -- IN/OUT INSTRUCTIONS  
           '0'&dex_adr5port when (idc_cbi or idc_sbi or idc_sbic or idc_sbis) ='1'    else  -- CBI/SBI (READ PHASE) + SBIS/SBIC
		   '0'&cbi_sbi_io_adr_tmp when (cbi_st or sbi_st)='1' else	-- CBI/SBI (WRITE PHASE)
		    ramadr_int(6)&ramadr_int(4 downto 0);                                                   -- LD/LDS/LDD/ST/STS/STD

-- ramre 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                    -- LD/LDD/LDS/POP/
--             ret_st1 or ret_st2 or reti_st1 or reti_st2);     -- RET/RETI

DataMemoryRead:process(clk,nrst)
begin
if nrst='0' then -- Reset
 ramre_int <= '0';
  elsif (clk='1' and clk'event) then -- Clock
case ramre_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_ld_x or idc_ld_y or idc_ldd_y or idc_ld_z or idc_ldd_z or  -- LD/LDD instruction	
	 lds_st1 or                                                     -- LDS instruction	
	 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_st2 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 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(clk,nrst)
begin
if nrst='0' then -- Reset
 ramwe_int <= '0';
  elsif (clk='1' and clk'event) then -- Clock
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	
	 sts_st1 or                                                     -- STS instruction	
	 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_st2 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 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_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       -- +
              "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_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';

⌨️ 快捷键说明

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