📄 pm_fetch_dec.vhd
字号:
-- 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®_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 + -