📄 state_machine.v
字号:
// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Copyright (c) 2001 by Lattice Semiconductor Corporation
// --------------------------------------------------------------------
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code for use
// in synthesis for any Lattice programmable logic product. Other
// use of this code, including the selling or duplication of any
// portion is strictly prohibited.
//
// Disclaimer:
//
// This VHDL or Verilog source code is intended as a design reference
// which illustrates how these types of functions can be implemented.
// It is the user's responsibility to verify their design for
// consistency and functionality through the use of formal
// verification methods. Lattice Semiconductor provides no warranty
// regarding the use or functionality of this code.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 408-826-6000 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// Revision History :
// --------------------------------------------------------------------
// Ver :| Author :| Mod. Date :| Changes Made:
// v1.0 :| D.S. :| 12/16/98 :| Initial Creation
// v1.1 :| D.S. :| 10/05/99 :| added be_oe
// --------------------------------------------------------------------
//
// Module state_machine
//
/* This module is called state_machine. It's purpose is to control
the bus cycle timng of the PCI and bkend Interface signals.
The outputs of this block also control output enables for
3 state buffers in the design.
The PCI Target State Machine is at the heart of this Reference Design.
The State Machine goes from the idle state to one of three possible
paths during any given PCI operation. While in the PCI address phase
of a transaction the values on pci_cbe_l and pci_idsel determine
if the transaction is a: Configuration Read or Write,
Memory-I/O Read, or a Memory-I/O Write.
The designer can modify the state machine HDL code if the
functionality of the Back End Device has special system requirements.
It may be necessary to implement wait states, or new enable signals
for particular applications. These would require modifications to
the HDL code, but embedded HDL comments will guide the designer
through the state machine implementation and signal descriptions.
*/
module state_machine (devsel_l, trdy_l, stop_l, pci_ad_oe,
dts_oe, par_oe, bk_oe, pci_ad_en, hit_ba0_l, hit_ba1_l,
pci_frame_l, pci_idsel, pci_irdy_l, pci_ad, pci_cbe_l,
pci_clk, pci_rst_l, abort_sig, data_stop_l, com,
data_write_l, ready_l, bkend_abort_l, count_rst_l, count_en_l,
retry_l, base_region0_l, base_region1_l, r_w_l, data_read_l,
be_oe);
output devsel_l; // input to 3 state
output trdy_l; // input to 3 state
output stop_l; // input to 3 state
output pci_ad_oe; // OE for PCI address bus
output dts_oe; // OE control for the devsel, trdy_l, stop_l (dts)
output par_oe; // OE control for pci_par
output bk_oe; // OE control for bkend_dat bus
output pci_ad_en; // clock enable for the PCI address latch register
output abort_sig; // sets the status register bit for abort
output data_write_l; // used as a clock enable for the pci_clk
// to the bkend device
output count_rst_l; // async reset to the retry counter
output count_en_l; // the clock enable for the retry counter
output base_region0_l; // chip selects to the backend
output base_region1_l; // chip selects to the backend
output r_w_l; // read == 1 & write == 0
output data_read_l; // the read strobe for the backend device
output be_oe; // enables the byte enables for the backend
input hit_ba0_l; // The pci address is in base address 0
input hit_ba1_l; // The pci address is in base address 1
input pci_frame_l; // The pci_frame_l signal
input pci_idsel; // The pci idsel signal
input pci_irdy_l; // The pci irdy signal
input [31:0] pci_ad; // raw pci address data bus
input [3:0] pci_cbe_l; // The command or byte enables
input pci_clk;
input pci_rst_l;
input bkend_abort_l; // bkend has had a fatal error
input data_stop_l; // bkend requesting transaction to stop
input [1:0] com;
input ready_l; // bkend is ready to start a transaction cycle
input retry_l; // when active retry counter has timed out
/*********************************************/
/* Some outputs of this block are registered. */
/* The reg declarations are listed here */
/*********************************************/
reg devsel_l;
reg trdy_l, stop_l, pci_ad_oe;
reg dts_oe, par_oe, bk_oe;
reg pci_ad_en;
reg be_oe;
reg abort_sig;
reg count_rst_l, count_en_l;
reg base_region0_l, base_region1_l;
reg r_w_l;
reg read_flag, single_read_flag;
/*********************************************/
/* begin statemachine declarations */
/* Note: synthesis attributes are synthesis */
/* tool specific. */
/*********************************************/
reg [11:0] /* exemplar enum state_type */ cstate;
parameter [11:0] /* exemplar enum state_type */
idle = 12'b0000_0000_0001,
con_wait = 12'b0000_0000_0010,
con_wait2 = 12'b0000_0000_0100,
con = 12'b0000_0000_1000,
read_wait = 12'b0000_0001_0000,
rw = 12'b0000_0010_0000,
rw_wait = 12'b0000_0100_0000,
rw_wait2 = 12'b0000_1000_0000,
last_rw = 12'b0001_0000_0000,
backoff = 12'b0010_0000_0000,
retry = 12'b0100_0000_0000,
abort = 12'b1000_0000_0000;
/***********************************************/
/* The following `defines are defined here to */
/* keep the state machine clean. */
/***********************************************/
`define config_read (pci_cbe_l == 4'b1010)
`define config_write (pci_cbe_l == 4'b1011)
`define func_zero_type_zero (pci_ad[10:8] == 3'b000) && (pci_ad[1:0] == 2'b00)
`define write_ba0 pci_addr[7:2] == 6'h10
`define write_ba1 pci_addr[7:2] == 6'h14
`define no_config (!pci_idsel && !pci_frame_l)
`define io_read ((pci_cbe_l == 4'b0010) && com[0])
`define io_write ((pci_cbe_l == 4'b0011) && com[0])
`define mem_read ((pci_cbe_l == 4'b0110) && com[1])
`define mem_write ((pci_cbe_l == 4'b0111) && com[1])
// Notice: All outputs that go off the chip are registered,
// except for data_write_l and data_read_l.
// If an output is active low it ends with _l else it's
// active high.
// mealy state machine with synchronous outputs
always @ (posedge pci_clk or negedge pci_rst_l)
begin
if (!pci_rst_l) begin
cstate <= #1 idle;
devsel_l <= #1 1;
trdy_l <= #1 1;
stop_l <= #1 1;
pci_ad_oe <= #13 0;
dts_oe <= #13 0;
par_oe <= #13 0;
bk_oe <= #13 0;
abort_sig <= #1 0;
count_rst_l <= #1 1;
count_en_l <= #1 1;
base_region0_l <= #1 1;
base_region1_l <= #1 1;
r_w_l <= #1 1; // default to read
read_flag <= #1 0;
single_read_flag <= #1 0;
end
else begin
case (cstate) // parallel_case full_case
idle:
begin
if ((`config_read || `config_write) && `func_zero_type_zero
&& !pci_frame_l && pci_idsel) begin
cstate <= #1 con_wait;
dts_oe <= #13 1; // takes 1 tic
if (`config_read) begin
pci_ad_oe <= #13 1; // takes 1 tic
end
else begin // config write
pci_ad_oe <= #13 0; // takes 1 tic
end
par_oe <= #13 0;
devsel_l <= #1 1; // disabled at first
trdy_l <= #1 1; // disabled at first
stop_l <= #1 1; // disabled at first
count_rst_l <= #1 1;
count_en_l <= #1 1;
abort_sig <= #1 0; // disable
base_region0_l <= #1 1;
base_region1_l <= #1 1;
r_w_l <= #1 1;
end
else if ((`io_read || `mem_read) && `no_config ) begin
cstate <= #1 rw_wait;
read_flag <= #1 1; // set because it's a read
dts_oe <= #13 1; // takes 1 tic get ready to drive
devsel_l <= #1 1; // disabled at first
trdy_l <= #1 1; // disabled at first
stop_l <= #1 1; // disabled at first
count_rst_l <= #1 0; // reset the counter
count_en_l <= #1 1;
abort_sig <= #1 0; // disable
base_region0_l <= #1 1;
base_region1_l <= #1 1;
r_w_l <= #1 1; // default to read
end
else if ((`io_write || `mem_write) && `no_config )begin
cstate <= #1 rw_wait;
read_flag <= #1 0; // clear because it's a write
dts_oe <= #13 1; // takes 1 tic get ready to drive
devsel_l <= #1 1; // disabled at first
trdy_l <= #1 1; // disabled at first
stop_l <= #1 1; // disabled at first
count_rst_l <= #1 0; // reset the counter
count_en_l <= #1 1;
abort_sig <= #1 0; // disable
base_region0_l <= #1 1;
base_region1_l <= #1 1;
r_w_l <= #1 1; // default to a read at first
end
else begin
cstate <= #1 idle;
devsel_l <= #1 1;
trdy_l <= #1 1;
stop_l <= #1 1;
pci_ad_oe <= #13 0;
dts_oe <= #13 0;
par_oe <= #13 0;
bk_oe <= #13 0;
abort_sig <= #1 0;
count_rst_l <= #1 1;
count_en_l <= #1 1;
abort_sig <= #1 0; // disable
base_region0_l <= #1 1;
base_region1_l <= #1 1;
r_w_l <= #1 1;
end
end
con_wait:
begin
// always go to con_wait2
cstate <= con_wait2;
devsel_l <= #1 0;
end
con_wait2:
begin
cstate <= con;
par_oe <= #13 1; // takes one tic
trdy_l <= #1 0; // ready to transfer next tic
if (!pci_frame_l)
stop_l <= #1 0; // burst config not supported
// disconnect A or B
else
stop_l <= #1 1; // single Config is OK
end
con:
begin
if (!pci_irdy_l) begin
// transfer data
cstate <= backoff;
devsel_l <= #1 1;
trdy_l <= #1 1;
stop_l <= #1 1;
pci_ad_oe <= #13 0; // disable
end
else begin
// wait for pci_irdy_l == 0
cstate <= con;
devsel_l <= #1 0;
trdy_l <= #1 0;
if (!pci_frame_l)
stop_l <= #1 0; // burst config not supported
// disconnect A or B
else
stop_l <= #1 1; // single Config is OK
end
end
/* if we have a hit rw_wait turns on dts_oe.
and asserts the base address region signal.
we need to wait till rw_wait2 to change
any dts signal.
d=devsel_l t=trdy_l s=stop_l
*/
rw_wait:
begin
if (pci_frame_l && read_flag) begin
single_read_flag <= #1 1; // single cycle read
end
else begin
single_read_flag <= #1 0; // i.e. burst read
end
// Irdy_l can not be late, the initiator must be ready
// here. The target relies on it.
if (!hit_ba0_l) begin
cstate <= #1 rw_wait2;
count_rst_l <= #1 1; // disable
count_en_l <= #1 0; // enable
base_region0_l <= #1 0; // enable
base_region1_l <= #1 1; // disable
dts_oe <= #13 1; // takes 1 tic get ready to drive
devsel_l <= #1 1; // disabled at first
trdy_l <= #1 1; // disabled at first
stop_l <= #1 1; // disabled at first
if (read_flag) begin
bk_oe <= #13 0; // disable OE
r_w_l <= #1 1;
end
else begin
bk_oe <= #13 1; // enable OE
r_w_l <= #1 0;
end
end
else if (!hit_ba1_l) begin
cstate <= #1 rw_wait2;
count_rst_l <= #1 1; // disable
count_en_l <= #1 0; // enable
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -