|
Message
From: Umair Siddiqui<umairsiddiqui84@g...>
Date: Wed Sep 7 00:59:10 CEST 2005
Subject: [oc] hpc-16: continued ack_i problems
the bus controling issues are creating problems. The complete code of cpu along with documentation is posted on OpenCores.org as *HPC-16* project. cpu only supports single read/write cycles. Currently I just simulating the CPU on modelsim, not tested on cpu. All signal assignments are in zero time, no timing info in CPU RTL or RAM models. i.e no "after unit_time". this is my first cpu...please help //////////////////////////////////////////// --// this code of sync, i tried both archs, --// first one delays the "ack_sync" arrival --// second one donot delay the async arrival
entity sync is port ( d : in std_logic; clk : in std_logic; q : out std_logic ); end sync;
architecture Behavioral of sync is signal t : std_logic; begin process(clk) begin if rising_edge(CLK) then t <= d; q <= t; end if; end process; end Behavioral;
architecture behave2 of sync is signal t : std_logic; begin process(clk , d) begin if d = '1' then t <= '1'; q <= '1'; elsif rising_edge(clk) then t <= '0'; q <= t; end if; end process; end behave2;
///////////////////////////////////// --// control unit code fragments to --// highlight suspicious code related to --// bus controlling
entity con1 is port( CLK_I : in std_logic; RST_I : in std_logic; ACK_I : in std_logic; SEL_O : out std_logic_vector(1 downto 0); STB_O : out std_logic; CYC_O : out std_logic; WE_O : out std_logic; ir_high : in std_logic_vector(7 downto 0); ... -- ***************************************** -- -- ** DAT_IO (not separate DAT_I & DAT_O) ** -- -- ** and ADR_O are ports of datapath ** -- -- ***************************************** -- -- ** may be DAT_IO is creating all evil! ** -- -- ***************************************** -- ); end con1; architecture rtl of con1 is signal rst_sync : std_logic; signal ack_sync : std_logic; signal intr_sync : std_logic; signal cur_state , nxt_state : state; signal cur_ic : ic; ... begin rsync : sync port map ( d => RST_I, clk => CLK_I, q => rst_sync ); async : sync port map ( d => ACK_I, clk => CLK_I, q => ack_sync ); --//////////////////////////////////////////////////////// -- combinational predecoding decode: cur_ic <= ic_mov_rn_rm when ir_high = mov_rn_rm else ic_mov_sp_rm when ir_high = mov_sp_rm else ic_mov_rn_sp when ir_high = mov_rn_sp else ic_ld_rn_rb when ir_high = ld_rn_rb else ic_ld_rn_rb_disp when ir_high = ld_rn_rb_disp else ... ic_hlt when ir_high(7 downto 3) = hlt else
ic_invalid;
--/////////////////////////////////////////////////////////////
-- main fsm-------------
process(CLK_I, rst_sync)
begin
if rst_sync = '1' then
cur_state <= reset;
elsif rising_edge(CLK_I) then
cur_state <= nxt_state;
end if;
end process;
process(cur_state, cur_ic, ir_high(2 downto 0), ack_sync, rst_sync,
<other signals>)
begin
-- defualt assigns to avoid latch
SEL_O <= "00"; STB_O <= '0'; CYC_O <= '0'; WE_O <= '0'; <other asigns>
-- ****************************************************
-- ** note: no default assign for "nxt_state"
-- ** should i add: "nxt_state <= reset"
-- ****************************************************
--//////////////////////////////////////
case cur_state is
--//////////////////////////////////////
when reset =>
-- generate control signals to reset the Program Counter
(pc) and FLAGS
if rst_sync = '0' then
nxt_state <= fetch0;
else
nxt_state <= reset;
end if;
--//////////////////////////////////////
when fetch0 =>
-- assign pc contents to memory address reg(connected to
address bus): mar <= pc
-- increament pc by two: pc <= pc + 2
nxt_state <= fetch1;
--///////////////////////////////////////
when fetch1 =>
-- start instruction fetch cycle
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1';
-- prepare instruction register (ir) for instruction loading
ir_ce <= '1';
nxt_state <= fetch2;
--///////////////////////////////////////
when fetch2 =>
if ack_sync = '1' then
-- ********************************************************* --
-- ** instruction register should be loaded at this point ** --
-- ** otherwise control unit should stay in this state. ** --
-- ** this another reason for adding *sync* to ack_i ** --
-- ** (no need to add wait state circuit for SPARTAN 3 ** --
-- ** BRAMS) ** --
-- ** ?? is this a clean way ?? ** --
-- ********************************************************* --
-- ** any way stop the bus cycle, since we have recieved ** --
-- ** the *ack_sync* ** --
-- ********************************************************* --
-- ** another issue: ** --
-- ** in a "zero delay simulation", if stb_o controls the ** --
-- ** controls the chip-select of RAM, the "cs" of ram ** --
-- ** will be deasserted, resulting in immediate high-z on** --
-- ** data bus, in fact my whole simulation start running ** --
-- ** in delta time, if i remove the sync from ack_i! ** --
-- ********************************************************* --
-- ** note: for any read or write cycle, the cpu ** --
-- ** *does not wait* for ack_sync to become deasserted ** --
-- ** so in simulation, ack_sync generated for fetch2 ** --
-- ** is falsely reused for exec2. ** --
-- ** this would be obvious if use first arch of sync, ** --
-- ** in second arch you will observe a glitch at this ** --
-- ** time. ** --
-- ********************************************************* --
nxt_state <= exec0;
else
-- continue instruction fetch & prepare ir and stay in this state
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1'; I_CYC_O <= '1';
ir_ce <= '1';
nxt_state <= fetch2;
end if;
--///////////////////////////////////////
-- ** execution phase 0** --
when exec0 =>
-- ** based on current instruction type! ** --
case cur_ic is
-- **************************************** --
-- ** several types of instructions, ** --
-- ** please consider *int* and *iret* ** --
-- ** interrupt call and return ** --
-- **************************************** --
-- ** interrupt call: int <4-bit integer>** --
-- ** FLAGS and then PC ** --
-- ** are pushed into stack, then PC ** --
-- ** is assigned {vector no. x 8} ** --
-- **************************************** --
-- ** interrupt ret: iret ** --
-- ** memory words are poped into PC and ** --
-- ** then into FLAGS ** --
-- **************************************** --
when ic_int =>
-- stack pointer is decrmented by two : sp = old sp - 2
-- mar is also assigned with this new value: mar = old sp - 2
-- "mem data reg for output" (mdro) which is
connected to data bus
-- is assigned zero extended FLAGS: mdro = flags
nxt_state <= exec1;
----------------------------------------
when ic_iret =>
-- increament the sp by two: sp = old sp + 2
-- but assign mar old value: mar = old sp
nxt_state <= exec1;
----------------------------------------
-- other instruction types
----------------------------------------
when ic_invalid =>
-- handle invalid instructions by throwing exception
-- separate "state chain" to handle the issue
nxt_state <= invalid0;
----------------------------------------------
end case;
--///////////////////////////////////////
-- ** execution phase 1** --
when exec1 =>
case cur_ic is
----------------------------------------------
when ic_iret =>
-- read data word (PC)
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1';
-- prepare "mem data reg for input" (mdri) for data loading
mdri_ce <= '1';
--
nxt_state <= exec2;
----------------------------------------------
when ic_int =>
-- assert the tri state control
mdro_oe <= '1';
-- write data word (FLAGS)
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1'; WE_O <= '1';
--
nxt_state <= exec2;
----------------------------------------------
-- other instruction types
----------------------------------------------
-- ***************************************** --
when others =>
null;
-- ***************************************** --
end case;
--///////////////////////////////////////
-- ** execution phase 2** --
when exec2 =>
case cur_ic is
when ic_int =>
if ack_sync = '1' then
-- *****************************************
-- ** now we can start another bus cycle:
-- ** prepare to push PC
-- *****************************************
-- mar = old sp -2
-- sp = old sp - 2
-- mdro = pc
nxt_state <= exec3;
else
--*****************************************
--** otherwise FLAGS may not be written
--** continue the write cycle and stay in this state
--*****************************************
mdro_oe <= '1';
-- try writing data word
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1'; WE_O <= '1';
--
nxt_state <= exec2;
end if;
-----------------------------------------
when ic_iret =>
if ack_sync = '1' then
-- ****************************************
-- ** mdri might be loaded with mem word,
-- ** copy it to pc, prepare for another
-- ** pop
-- ****************************************
-- pc = mdri
-- sp = old sp + 2
-- mar = old sp
--
nxt_state <= exec3;
else
-- continue reading data word
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1';
--
mdri_ce <= '1';
--
nxt_state <= exec2;
end if;
--------------------------------------------
-- other instruction type
--------------------------------------------
when others =>
null;
-------------------------------------------
--///////////////////////////////////////
when exec3 =>
case cur_ic is
when ic_int =>
mdro_oe <= '1';
-- start writting PC (write bus cycle)
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1'; WE_O <= '1';
--
nxt_state <= exec4;
----------------------------------------------
when ic_iret =>
mdri_ce <= '1';
-- try reading FLAGS (read bus cycle)
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1';
--
nxt_state <= exec4;
----------------------------------------------
when others =>
null;
----------------------------------------------
end case;
--///////////////////////////////////////
when exec4 =>
case cur_ic is
----------------------------------------------
when ic_int =>
if ack_sync = '1' then
-- pc = ext(ir(3..0)) * 8
-- execution complete, poll the interrupt pin
nxt_state <= int_chk;
else
mdro_oe <= '1';
-- continue writting PC
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1'; WE_O <= '1';
--
nxt_state <= exec4;
end if;
----------------------------------------------
when ic_iret =>
if ack_sync = '1' then
-- flags = mdri
--
nxt_state <= int_chk;
else
mdri_ce <= '1';
-- try reading FLAGS
SEL_O <= "11"; STB_O <= '1'; CYC_O <= '1';
--
nxt_state <= exec4;
end if;
----------------------------------------------
when others =>
null;
----------------------------------------------
end case;
--//////////////////////////////////////
-- rest of states
--/////////////////////////////////////
end case;
end process;
end rtl;
///////////////////////////////////////////////////////////////////////////////////////////
|
 |