📄 state_machine.v
字号:
// Module state_machine
//
/* This module is called state_machine. It's purpose is to control
the bus cycle timing 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 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
(
input pci_rst_l, pci_clk, pci_frame_l, pci_idsel, pci_irdy_l,
input [3:0] pci_cbe, // The command or byte enables
input [31:0] pci_ad, // raw pci address data bus
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 [1:0] com,
inout reg devsel_l, // input to 3 state
inout reg trdy_l, // input to 3 state
inout reg stop_l, // input to 3 state
output reg pci_ad_oe, // OE for PCI address bus
output reg par_oe, // OE control for pci_par
output reg bk_ba0_l, // chip selects to the backend
output reg bk_ba1_l, // chip selects to the backend
output reg r_w_l, // read == 1 & write == 0
output reg data_wr_l, // used as a clock enable for the pci_clk to the bkend device
output reg data_rd_l, // the read strobe for the backend device
output reg [3:0] tps,
output reg [31:0] pci_addr_reg, // first clock's address
output reg [3:0] pci_cbe_reg, // first clock's command
output reg pci_idsel_reg // config cycle ID
);
/*********************************************/
/* begin statemachine declarations */
/*********************************************/
reg read_flag; // data cycle: read == 1; write == 0;
reg con_read_flag; // config cycle: read == 1; write == 0;
reg [11:0] cstate;
parameter idle = 12'b0000_0000_0001,
con_wait_med = 12'b0000_0000_0010,
con_wait_slw = 12'b0000_0000_0100,
con = 12'b0000_0000_1000,
rw_wait_hit = 12'b0000_0001_0000,
rw_wait = 12'b0000_0010_0000,
read_wait = 12'b0000_0100_0000,
read_last = 12'b0000_1000_0000,
write_wait = 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 func_zero_type_zero ((pci_ad[10:8] == 3'b000) && (pci_ad[1:0] == 2'b00))
`define no_config (!pci_idsel && !pci_frame_l)
`define config_read (pci_cbe == 4'b1010)
`define config_write (pci_cbe == 4'b1011)
`define io_read ((pci_cbe == 4'b0010) && com[0])
`define io_write ((pci_cbe == 4'b0011) && com[0])
`define mem_read ((pci_cbe == 4'b0110) && com[1])
`define mem_write ((pci_cbe == 4'b0111) && com[1])
`define delay #3
// mealy state machine with synchronous outputs
always @ (posedge pci_clk or negedge pci_rst_l) begin
if (!pci_rst_l) begin // System Reset
cstate <= `delay idle;
devsel_l <= `delay 1'bZ;
trdy_l <= `delay 1'bZ;
stop_l <= `delay 1'bZ;
pci_ad_oe <= `delay 0;
par_oe <= `delay 0;
bk_ba0_l <= `delay 1;
bk_ba1_l <= `delay 1;
data_rd_l <= `delay 1;
data_wr_l <= `delay 1;
r_w_l <= `delay 0; // default to write
read_flag <= `delay 0; // default to write
con_read_flag <= `delay 0; // default to write
end
else begin
case (cstate) // parallel_case full_case
idle: begin
// 总线地址期:锁存pci_cbe, pci_addr 及 pci_idsel 信号。
if (!pci_frame_l) begin
pci_addr_reg <= #1 pci_ad; // register address
pci_cbe_reg <= #1 pci_cbe;
pci_idsel_reg <= #1 pci_idsel;
end
else begin
pci_addr_reg <= #1 pci_addr_reg;
pci_cbe_reg <= #1 pci_cbe_reg;
pci_idsel_reg <= #1 pci_idsel_reg;
end
//
if ((`config_read || `config_write) && `func_zero_type_zero && !pci_frame_l && pci_idsel) begin
cstate <= `delay con_wait_med;
devsel_l <= `delay 1; // disabled at first
trdy_l <= `delay 1; // disabled at first
stop_l <= `delay 1; // disabled at first
par_oe <= `delay 0;
if (`config_read) // config read
con_read_flag <= `delay 1; // takes 1 tic
else // config write
con_read_flag <= `delay 0; // takes 1 tic
tps[3] <= 1;
end
//else if ((`io_read || `mem_read) && `no_config ) begin // Intel CPU
else if ((`io_read || `mem_read) && !pci_frame_l) begin // AMD CPU
cstate <= `delay rw_wait_hit;
devsel_l <= `delay 1;
trdy_l <= `delay 1;
stop_l <= `delay 1;
pci_ad_oe <= `delay 0;
par_oe <= `delay 0;
bk_ba0_l <= `delay 1;
bk_ba1_l <= `delay 1;
data_rd_l <= `delay 1;
data_wr_l <= `delay 1;
r_w_l <= `delay 0;
read_flag <= `delay 1; // set because it's a read
tps[3] <= 1;
end
//else if ((`io_write || `mem_write) && `no_config ) begin // Intel CPU
else if ((`io_write || `mem_write) && !pci_frame_l) begin // AMD CPU
cstate <= `delay rw_wait_hit;
devsel_l <= `delay 1;
trdy_l <= `delay 1;
stop_l <= `delay 1;
pci_ad_oe <= `delay 0;
par_oe <= `delay 0;
bk_ba0_l <= `delay 1;
bk_ba1_l <= `delay 1;
data_rd_l <= `delay 1;
data_wr_l <= `delay 1;
r_w_l <= `delay 0;
read_flag <= `delay 0; // clear because it's a write
tps[3] <= 1;
end
else begin // idle
cstate <= `delay idle;
devsel_l <= `delay 1'bZ;
trdy_l <= `delay 1'bZ;
stop_l <= `delay 1'bZ;
pci_ad_oe <= `delay 0;
par_oe <= `delay 0;
bk_ba0_l <= `delay 1;
bk_ba1_l <= `delay 1;
data_rd_l <= `delay 1;
data_wr_l <= `delay 1;
r_w_l <= `delay 0; // default to write
read_flag <= `delay 0; // default to write
con_read_flag <= `delay 0; // default to write
tps[3:0] <= 4'b0;
end
end
con_wait_med: begin // 2'th clock : config cycle;
cstate <= `delay con_wait_slw;
devsel_l <= `delay 0;
if (con_read_flag) // config read
pci_ad_oe <= `delay 1; // takes 1 tic
else // config write
pci_ad_oe <= `delay 0; // takes 1 tic
tps[2] <= 1;
end
con_wait_slw: begin // 3'th clock : config cycle;
// ready to transfer
cstate <= `delay con;
trdy_l <= `delay 0; // ready to transfer next tic
if (!pci_frame_l)
stop_l <= `delay 0; // burst config not supported
else
stop_l <= `delay 1; // single Config is OK
tps[1] <= 1;
end
con: begin // 4'th clock : config cycle;
if (!pci_irdy_l) begin // transfer data
cstate <= `delay backoff;
devsel_l <= `delay 1;
trdy_l <= `delay 1;
stop_l <= `delay 1;
if (con_read_flag) // config read
par_oe <= `delay 1;
end
else begin // wait for pci_irdy_l == 0
cstate <= `delay con;
trdy_l <= `delay 0;
if (!pci_frame_l)
stop_l <= `delay 0; // burst config not supported
// disconnect A or B
else
stop_l <= `delay 1; // single Config is OK
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -