sdmmqy
Newbie level 1
dior_r
entity pioIntfc is
end pioIntfc;
architecture arch of pioIntfc is
-- timer register that counts down times for the phases of the disk R/W operation
signal timer_r, timer_x : natural range OP_CYCLES downto 0;
-- PIO mode timing parameters converted into unsigned clock cycles for clarity
-- constant OP_CYCLES : unsigned := TO_UNSIGNED(OP_CYCLES_N, timer_r'length);
-- constant SETUP_CYCLES : unsigned := TO_UNSIGNED(SETUP_CYCLES_N, timer_r'length);
-- constant PULSE_CYCLES : unsigned := TO_UNSIGNED(PULSE_CYCLES_N, timer_r'length);
-- constant HOLD_CYCLES : unsigned := TO_UNSIGNED(HOLD_CYCLES_N, timer_r'length);
-- states of the PIO interface state machine
type cntlState is (
RW_SETUP, -- setup address/data before read pulse
RD_PULSE, -- read pulse active
RD_HOLD, -- hold address/data after read pulse
WR_PULSE, -- write pulse active
WR_HOLD -- hold address/data after write pulse
);
signal state_r, state_x : cntlState; -- state register and next state
-- PIO interface registers
signal pioBusy_r, pioBusy_x : std_logic; -- R/W in-progress register
signal dior_r, dior_x : std_logic; -- disk read signal register
signal diow_r, diow_x : std_logic; -- disk write signal register
signal da_r, da_x : std_logic_vector(pioAddr'range); -- disk register address register
signal ddOut_r, ddOut_x : std_logic_vector(ddOut'range); -- data output to disk register
signal ddOutEnbl_r, ddOutEnbl_x : std_logic; -- enable data output to disk register
signal ddIn_r, ddIn_x : std_logic_vector(ddIn'range); -- data input from disk register
-- reports the status of the PIO interface
signal status_r, status_x : std_logic_vector(3 downto 0);
-- debounce counter for the interrupt request input
signal intrqCnt_r, intrqCnt_x : std_logic_vector(3 downto 0);
constant DEBOUNCE_CNT : natural := 10;
signal pioIntrq_r, pioIntrq_x : std_logic;
signal intrq_r, intrq_x : std_logic;
begin
-----------------------------------------------------------
-- attach some internal signals to the host and disk ports
-----------------------------------------------------------
dior_n <= dior_r;
diow_n <= diow_r;
da <= da_r(da'range);
cs0_n <= da_r(3);
cs1_n <= da_r(4);
ddOut <= ddOut_r;
ddOutEnbl <= ddOutEnbl_r;
pioDOut <= ddIn_r; -- output data to host is the input data from the disk
pioBusy <= pioBusy_r;
pioIntrq <= pioIntrq_r;
status <= status_r;
dmack_n <= '1'; -- never acknowledge DMA requests from disk
-----------------------------------------------------------
-- compute the next state and outputs
-----------------------------------------------------------
combinatorial : process(pioRd, pioWr, pioAddr, pioDIn, state_r, timer_r, dior_r, pioBusy_r,
diow_r, da_r, ddOut_r, ddOutEnbl_r, ddIn_r, ddIn, status_r)
begin
-----------------------------------------------------------
-- setup default values for signals
-----------------------------------------------------------
state_x <= state_r;
dior_x <= dior_r;
diow_x <= diow_r;
da_x <= da_r;
ddOut_x <= ddOut_r;
ddOutEnbl_x <= ddOutEnbl_r;
ddIn_x <= ddIn_r;
pioBusy_x <= pioBusy_r;
status_x <= status_r;
-----------------------------------------------------------
-- update the timers
-----------------------------------------------------------
-- main timer for sequencing the phases of the R/W waveforms
if timer_r /= 0 then
-- decrement the timer and do nothing else since the previous
-- phase has not completed yet.
timer_x <= timer_r - 1;
else
-- the previous phase has completed once the timer hits zero.
-- By default, leave the timer at zero. A R/W op will set it
-- to non-zero below.
timer_x <= timer_r; ----------------------------------------------------------- -- compute the next state and outputs
-----------------------------------------------------------
case state_r is
-----------------------------------------------------------
-- wait for a disk read or write operation
-----------------------------------------------------------
when RW_SETUP =>
dior_x <= '1'; -- don't read or write the disk until requested
diow_x <= '1';
--ddOutEnbl_x <= NO; -- don't drive disk data bus until requested
if(pioRd ='0') then
-- a read operation is requested
--pioBusy_x <= YES; -- set busy bit
da_x <= pioAddr; -- output disk register address
timer_x <= 10;--SETUP_CYCLES; -- set timer for address setup
state_x <= RD_PULSE; -- next state after address setup completes
status_x <= "0010";
elsif(pioWr = '0') then
-- a write operation is requested
-- pioBusy_x <= YES; -- set busy bit
da_x <= pioAddr; -- output disk register address
ddOut_x <= pioDIn; -- output data to disk
ddOutEnbl_x <= '1'; -- enable output bus
timer_x <= SETUP_CYCLES; -- set timer for address/data setup
state_x <= WR_PULSE; -- next state after address/data setup completes
status_x <= "0100";
else
-- no operation is requested
pioBusy_x <= '0'; -- clear busy bit
state_x <= RW_SETUP; -- return to this state and wait for R/W request
status_x <= "0001";
end if;
-----------------------------------------------------------
-- pulse disk read control signal
-----------------------------------------------------------
when RD_PULSE =>
dior_x <= '0'; -- lower disk read control line
timer_x <= PULSE_CYCLES; -- load duration of read pulse
state_x <= RD_HOLD; -- next state after pulse completes
-----------------------------------------------------------
-- get data and hold address after read pulse ends
-----------------------------------------------------------
when RD_HOLD =>
ddIn_x <= ddIn; -- load the data from the disk
dior_x <= '1'; -- terminate the read pulse
timer_x <= HOLD_CYCLES; -- insert hold period after read operation
state_x <= RW_SETUP; -- look for another operation after the hold period
-----------------------------------------------------------
-- pulse disk write control signal
-----------------------------------------------------------
when WR_PULSE =>
diow_x <= '0'; -- lower disk write control line
timer_x <= PULSE_CYCLES; -- load duration of write pulse
state_x <= WR_HOLD; -- next state after pulse completes
-----------------------------------------------------------
-- hold address and data after write pulse ends
-----------------------------------------------------------
when WR_HOLD =>
diow_x <= '1'; -- terminate the write pulse
timer_x <= HOLD_CYCLES; -- insert hold period after write operation
state_x <= RW_SETUP; -- look for another operation after the hold period
-----------------------------------------------------------
-- unknown state
-----------------------------------------------------------
when others =>
state_x <= RW_SETUP; -- reset state if in erroneous state
status_x <= "1000";
end case;
end if;
end process combinatorial;
-----------------------------------------------------------
-- update registers on the appropriate clock edge
-----------------------------------------------------------
update : process(pioRst, clk)
begin
if pioRst = '1' then
-- asynchronous reset
state_r <= RW_SETUP;
timer_r <= 0;
pioBusy_r <= '0';
pioIntrq_r <='0';
intrq_r <= '0';
intrqCnt_r <= (others => '0');
dior_r <='1';
diow_r <= '1';
da_r <= (others => '0');
ddOut_r <= (others => '0');
ddOutEnbl_r <= '0';
ddIn_r <= (others => '0');
status_r <= (others => '0');
elsif rising_edge(clk) then
state_r <= state_x;
timer_r <= timer_x;
pioBusy_r <= pioBusy_x;
pioIntrq_r <= pioIntrq_x;
intrq_r <= intrq_x;
intrqCnt_r <= intrqCnt_x;
dior_r <= dior_x;
diow_r <= diow_x;
da_r <= da_x;
ddOut_r <= ddOut_x;
ddOutEnbl_r <= ddOutEnbl_x;
ddIn_r <= ddIn_x;
status_r <= status_x;
end if; end process update;
end arch;
Added after 4 minutes:
only after time_x,timer_r decrease to 0. thanks a lot.
I check by modelsim, the codes is ok.
entity pioIntfc is
end pioIntfc;
architecture arch of pioIntfc is
-- timer register that counts down times for the phases of the disk R/W operation
signal timer_r, timer_x : natural range OP_CYCLES downto 0;
-- PIO mode timing parameters converted into unsigned clock cycles for clarity
-- constant OP_CYCLES : unsigned := TO_UNSIGNED(OP_CYCLES_N, timer_r'length);
-- constant SETUP_CYCLES : unsigned := TO_UNSIGNED(SETUP_CYCLES_N, timer_r'length);
-- constant PULSE_CYCLES : unsigned := TO_UNSIGNED(PULSE_CYCLES_N, timer_r'length);
-- constant HOLD_CYCLES : unsigned := TO_UNSIGNED(HOLD_CYCLES_N, timer_r'length);
-- states of the PIO interface state machine
type cntlState is (
RW_SETUP, -- setup address/data before read pulse
RD_PULSE, -- read pulse active
RD_HOLD, -- hold address/data after read pulse
WR_PULSE, -- write pulse active
WR_HOLD -- hold address/data after write pulse
);
signal state_r, state_x : cntlState; -- state register and next state
-- PIO interface registers
signal pioBusy_r, pioBusy_x : std_logic; -- R/W in-progress register
signal dior_r, dior_x : std_logic; -- disk read signal register
signal diow_r, diow_x : std_logic; -- disk write signal register
signal da_r, da_x : std_logic_vector(pioAddr'range); -- disk register address register
signal ddOut_r, ddOut_x : std_logic_vector(ddOut'range); -- data output to disk register
signal ddOutEnbl_r, ddOutEnbl_x : std_logic; -- enable data output to disk register
signal ddIn_r, ddIn_x : std_logic_vector(ddIn'range); -- data input from disk register
-- reports the status of the PIO interface
signal status_r, status_x : std_logic_vector(3 downto 0);
-- debounce counter for the interrupt request input
signal intrqCnt_r, intrqCnt_x : std_logic_vector(3 downto 0);
constant DEBOUNCE_CNT : natural := 10;
signal pioIntrq_r, pioIntrq_x : std_logic;
signal intrq_r, intrq_x : std_logic;
begin
-----------------------------------------------------------
-- attach some internal signals to the host and disk ports
-----------------------------------------------------------
dior_n <= dior_r;
diow_n <= diow_r;
da <= da_r(da'range);
cs0_n <= da_r(3);
cs1_n <= da_r(4);
ddOut <= ddOut_r;
ddOutEnbl <= ddOutEnbl_r;
pioDOut <= ddIn_r; -- output data to host is the input data from the disk
pioBusy <= pioBusy_r;
pioIntrq <= pioIntrq_r;
status <= status_r;
dmack_n <= '1'; -- never acknowledge DMA requests from disk
-----------------------------------------------------------
-- compute the next state and outputs
-----------------------------------------------------------
combinatorial : process(pioRd, pioWr, pioAddr, pioDIn, state_r, timer_r, dior_r, pioBusy_r,
diow_r, da_r, ddOut_r, ddOutEnbl_r, ddIn_r, ddIn, status_r)
begin
-----------------------------------------------------------
-- setup default values for signals
-----------------------------------------------------------
state_x <= state_r;
dior_x <= dior_r;
diow_x <= diow_r;
da_x <= da_r;
ddOut_x <= ddOut_r;
ddOutEnbl_x <= ddOutEnbl_r;
ddIn_x <= ddIn_r;
pioBusy_x <= pioBusy_r;
status_x <= status_r;
-----------------------------------------------------------
-- update the timers
-----------------------------------------------------------
-- main timer for sequencing the phases of the R/W waveforms
if timer_r /= 0 then
-- decrement the timer and do nothing else since the previous
-- phase has not completed yet.
timer_x <= timer_r - 1;
else
-- the previous phase has completed once the timer hits zero.
-- By default, leave the timer at zero. A R/W op will set it
-- to non-zero below.
timer_x <= timer_r; ----------------------------------------------------------- -- compute the next state and outputs
-----------------------------------------------------------
case state_r is
-----------------------------------------------------------
-- wait for a disk read or write operation
-----------------------------------------------------------
when RW_SETUP =>
dior_x <= '1'; -- don't read or write the disk until requested
diow_x <= '1';
--ddOutEnbl_x <= NO; -- don't drive disk data bus until requested
if(pioRd ='0') then
-- a read operation is requested
--pioBusy_x <= YES; -- set busy bit
da_x <= pioAddr; -- output disk register address
timer_x <= 10;--SETUP_CYCLES; -- set timer for address setup
state_x <= RD_PULSE; -- next state after address setup completes
status_x <= "0010";
elsif(pioWr = '0') then
-- a write operation is requested
-- pioBusy_x <= YES; -- set busy bit
da_x <= pioAddr; -- output disk register address
ddOut_x <= pioDIn; -- output data to disk
ddOutEnbl_x <= '1'; -- enable output bus
timer_x <= SETUP_CYCLES; -- set timer for address/data setup
state_x <= WR_PULSE; -- next state after address/data setup completes
status_x <= "0100";
else
-- no operation is requested
pioBusy_x <= '0'; -- clear busy bit
state_x <= RW_SETUP; -- return to this state and wait for R/W request
status_x <= "0001";
end if;
-----------------------------------------------------------
-- pulse disk read control signal
-----------------------------------------------------------
when RD_PULSE =>
dior_x <= '0'; -- lower disk read control line
timer_x <= PULSE_CYCLES; -- load duration of read pulse
state_x <= RD_HOLD; -- next state after pulse completes
-----------------------------------------------------------
-- get data and hold address after read pulse ends
-----------------------------------------------------------
when RD_HOLD =>
ddIn_x <= ddIn; -- load the data from the disk
dior_x <= '1'; -- terminate the read pulse
timer_x <= HOLD_CYCLES; -- insert hold period after read operation
state_x <= RW_SETUP; -- look for another operation after the hold period
-----------------------------------------------------------
-- pulse disk write control signal
-----------------------------------------------------------
when WR_PULSE =>
diow_x <= '0'; -- lower disk write control line
timer_x <= PULSE_CYCLES; -- load duration of write pulse
state_x <= WR_HOLD; -- next state after pulse completes
-----------------------------------------------------------
-- hold address and data after write pulse ends
-----------------------------------------------------------
when WR_HOLD =>
diow_x <= '1'; -- terminate the write pulse
timer_x <= HOLD_CYCLES; -- insert hold period after write operation
state_x <= RW_SETUP; -- look for another operation after the hold period
-----------------------------------------------------------
-- unknown state
-----------------------------------------------------------
when others =>
state_x <= RW_SETUP; -- reset state if in erroneous state
status_x <= "1000";
end case;
end if;
end process combinatorial;
-----------------------------------------------------------
-- update registers on the appropriate clock edge
-----------------------------------------------------------
update : process(pioRst, clk)
begin
if pioRst = '1' then
-- asynchronous reset
state_r <= RW_SETUP;
timer_r <= 0;
pioBusy_r <= '0';
pioIntrq_r <='0';
intrq_r <= '0';
intrqCnt_r <= (others => '0');
dior_r <='1';
diow_r <= '1';
da_r <= (others => '0');
ddOut_r <= (others => '0');
ddOutEnbl_r <= '0';
ddIn_r <= (others => '0');
status_r <= (others => '0');
elsif rising_edge(clk) then
state_r <= state_x;
timer_r <= timer_x;
pioBusy_r <= pioBusy_x;
pioIntrq_r <= pioIntrq_x;
intrq_r <= intrq_x;
intrqCnt_r <= intrqCnt_x;
dior_r <= dior_x;
diow_r <= diow_x;
da_r <= da_x;
ddOut_r <= ddOut_x;
ddOutEnbl_r <= ddOutEnbl_x;
ddIn_r <= ddIn_x;
status_r <= status_x;
end if; end process update;
end arch;
Added after 4 minutes:
only after time_x,timer_r decrease to 0. thanks a lot.
I check by modelsim, the codes is ok.