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