📄 parallel_interface.v
字号:
/***Parallel Interface*********************************************************/
//在读写操作时,读的时候,应首先启动本地端的控制信号,然后再启动local端的控制信号;在写
//操作的时候,应首先启动local端的控制信号,然后再启动本地端的控制信号.
//传输过程:
//读过程: 本地总线-------->local总线------->PCI总线
//写过程: PCI总线--------->local总线------->本地总线
module parallel_interface (
clock,reset_n,
addr_in,data_in,data_out,ready_n,
l_cmdo,abort_n,lt_framen,lt_ackn,lt_dxfrn,lt_tsr,
pi_addr,pi_data,pi_done_n,//data--addr
//buf_dir,
rtc_ad,rtc_cs_n,rtc_as,rtc_rw,rtc_ds,rtc_sqw,
ot_thr,OT_CNT,test_flag,
//Zarlink
pi_cs_n,
cpu_oe_n,
cpu_we_n,
cpu_ts_ale,
cpu_ta_n,
cpu_clk
//Frame
/* frame_cs_n,
frame_ale,
frame_rd_n,
frame_wr_n, */
//pfga_sig
/* sig_wr_n,
sig_oe,
sig_cs_n */
);
input clock;
input reset_n;
//Back end Interface from "pci_top"
input [21:0] addr_in;
input [31:0] data_in;
output [31:0] data_out;
output ready_n;
inout [3:0] l_cmdo;
output abort_n;
input lt_framen;
input lt_ackn;
input lt_dxfrn;
input [11:0] lt_tsr;
//Parallel Interface
output [29:2] pi_addr;
inout [31:0] pi_data;
input pi_done_n;
//Zarlink
output cpu_cs_n;
output cpu_oe_n;
output cpu_we_n;
output cpu_ts_ale;
input cpu_ta_n;
output cpu_clk;
//RTC
inout [7:0] rtc_ad;
output rtc_cs_n;
output rtc_as;
output rtc_rw;
output rtc_ds;
input rtc_sqw;
//Frame
/* output frame_cs_n;
output frame_ale;
output frame_rd_n;
output frame_wr_n;
//fpga_sig
output sig_wr_n;
output sig_oe;
output sig_cs_n; */
output test_flag;//For test
input [7:0] ot_thr;//Overtime threshold (wait for pi_done_n)
output [31:0] OT_CNT;//Over time error counter
reg [31:0] OT_CNT;
/******************************************************************************/
`define BAR0 (lt_tsr[0] == 1'b1) //local
`define BAR1 (lt_tsr[1] == 1'b1) //Zarlink
`define BAR2 (lt_tsr[2] == 1'b1) //Pmc4351
//`define BAR3 (lt_tsr[3] == 1'b1) //Fpga_sig
`define mem_read (l_cmdo == 4'b0110)
`define mem_write (l_cmdo == 4'b0111)
//`define ot_thr 8'b00111111 //Overtime threshold (wait for pi_done_n)
/******************************************************************************/
/******************************************************************************/
reg rtc_ad_ie;//input enable
reg rtc_ad_oe;//output enable
reg rtc_cs_n;
reg rtc_as;
reg rtc_rw;
reg rtc_ds;
reg [3:0] rtc_counter;
reg [7:0] rtc_ad_out_reg;
/******************************************************************************/
reg pi_done_n_dly;
reg pi_done_n_dly_dly;
always @(posedge clock or negedge reset_n)
begin
if(!reset_n) pi_done_n_dly <= 1'b1;
else pi_done_n_dly <= pi_done_n;
end
always @(posedge clock or negedge reset_n)
begin
if(!reset_n) pi_done_n_dly_dly <= 1'b1;
else pi_done_n_dly_dly <= pi_done_n_dly;
end
/******************************************************************************/
wire oe;//Enable pi_data output to IC
wire pi_done_n_wire = pi_done_n_dly_dly;
reg [31:0] pi_data_reg;
reg [29:8] pi_addr;
reg ready_n;
reg abort_n;
reg test_flag;
//Zarlink
reg cpu_cs_n;
reg cpu_oe_n;
reg cpu_we_n;
reg cpu_ts_ale;
// wire cpu_ta_n;
assign cpu_clk = clock;
//assign buf_dir = ! ((`BAR2 || `BAR3 || `BAR4 || `BAR5) && `mem_read);
assign oe = (`mem_write && `BAR1);
assign rtc_ad = (rtc_ad_oe) ? rtc_ad_out_reg : 8'hz;
assign pi_data = oe ? pi_data_reg : 32'hz;//pi_data并口数据总线
// assign data_out = (!oe) ? pi_data : 32'h0;
assign data_out = ((rtc_ad_ie) ? {24'h0 , rtc_ad} : (!oe) ? pi_data : 32'h0);
/******************************************************************************/
//addr_in 锁存
always @(posedge lt_framen or negedge reset_n)
begin
if(!reset_n)
pi_addr<= 22'h0;
else
begin
if(`mem_write || `mem_read)
begin
pi_addr[29:8] <= addr_in;
pi_addr[7:2] <=6'bz;
end
/* else if(!lt_framen && (`mem_write || `mem_read) && (`BAR2 || `BAR3))
begin
pi_addr[23:2] <= addr_in;
pi_addr[29:24]<=6'bz;
end */
else ;
end
end
/******************************************************************************/
//data_in 锁存
always @(negedge lt_dxfrn or negedge reset_n)
begin
if(!reset_n)
pi_data_reg <= 32'h0;
else
begin
if(`mem_write)
pi_data_reg <= data_in;
else ;
end
end
/******************************************************************************/
//State machine
reg [8:0] ot_count;//Overtime counter
reg [10:0] cstate;
parameter [8:0]
IDLE = 9'b000000001,
READ_ZL5011x = 9'b000000010,
READ_ZL5011x_1 = 9'b000000100,
WRITE_ZL5011x = 9'b000001000,
WRITE_ZL5011x_1 = 9'b000010000,
WRITE_ZL5011x_2 = 9'b000100000,
WRITE_ZL5011x_3 = 9'b001000000,
RTC_RD = 9'b010_0000_00,
RTC_WR = 9'b100_0000_00;
/******************************************************************************/
always @(posedge clock or negedge reset_n)
begin
if(!reset_n)
begin
ready_n <=1'b1;
abort_n <=1'b1;
//Zarlink--reset
cpu_we_n <= 1'b1;
cpu_oe_n <= 1'b1;
cpu_cs_n <= 1'b1;
cpu_ts_ale <= 1'b0;
rtc_ad_ie <= 1'b0;
rtc_ad_oe <= 1'b0;
rtc_cs_n <= 1'b1;
rtc_as <= 1'b0;
rtc_rw <= 1'b1;
rtc_ds <= 1'b1;
rtc_counter <= 8'h0;
rtc_ad_out_reg <= 8'h0;
/* //frame--reset
frame_ale <= 1'b1;
frame_cs_n <= 1'b1;
frame_rd_n <= 1'b1;
frame_wr_n <= 1'b1;
//fpga--reset
sig_cs_n <= 1'b1;
sig_wr_n <= 1'b1;
sig_oe <= 1'b1; */
//system--reset
ot_count <= 8'b0;
OT_CNT <= 32'b0;
test_flag <= 1'b0;
cstate <= IDLE;
end
else
begin
case(cstate)
IDLE:
begin
rtc_counter <= 8'h0;
rtc_ds <= 1'b1;
rtc_rw <= 1'b1;
rtc_cs_n <= 1'b1;
rtc_ad_ie <= 1'b0;
rtc_ad_oe <= 1'b0;
ot_count <= 8'b0; //计数初值设为0
if(!lt_framen && `mem_read && `BAR1)/*ZL5011x读*/
begin
cpu_we_n <= 1'b1; //开始读操作
cpu_oe_n <= 1'b0; //使能zl的读信号(read=0)
cpu_cs_n <= 1'b0; //片选有效
cpu_ts_ale <= 1'b1; //地址锁存有效
cstate <= READ_ZL5011x; //此时frame信号有效
end
else if(!lt_framen && `mem_write && `BAR1 )/*ZL5011x写*/
begin
ready_n <= 1'b0; //接收端已经准好了接收数据!
//cpu_we_n <= 1'b0;
cpu_cs_n <= 1'b0; //地址片选有效
cstate <= WRITE_ZL5011x;
end
else if(!lt_framen && `mem_read && `BAR2)
begin
//ready_n <= 1'b0;
cstate <= RTC_RD;//RTC read
end
else if(!lt_framen && `mem_write && `BAR2)
begin
ready_n <= 1'b0;
cstate <= RTC_WR;//RTC write
end
else
begin
ready_n <= 1'b1;
abort_n <=1'b1;
cpu_we_n <= 1'b1;
cpu_oe_n <= 1'b1;
cpu_cs_n <= 1'b1;
cpu_ts_ale <= 1'b0;
/* frame_ale <= 1'b1;
frame_cs_n <= 4'b1;
frame_rd_n <= 1'b1;
frame_wr_n <= 1'b1;
sig_cs_n <= 1'b1;
sig_wr_n <= 1'b1;
sig_oe <= 1'b1;*/
cstate <= IDLE;
end
end
READ_ZL5011x:
begin
cpu_ts_ale <= 1'b0;
ot_count <= ot_count + 1 ;
if(ot_count == ot_thr)
begin
ready_n <= 1'b1;
abort_n <= 1'b0;
ot_count <= 8'b0;
OT_CNT <= OT_CNT + 1;
cstate <= IDLE;
end
else if(!cpu_ta_n) //本地数据准好了,可以读入,等待本地总线准备好!
begin
ready_n <= 1'b0; //local bus 准备好
ot_count <= 8'b0;
cstate <= READ_ZL5011x_1;
end
else
cstate <= READ_ZL5011x;
end
READ_ZL5011x_1:
begin
ot_count <= ot_count + 1 ;
if(ot_count == ot_thr)
begin
abort_n <= 1'b0;
ot_count <= 8'b0;
OT_CNT <= OT_CNT + 1;
ready_n <= 1'b1;
cstate <= IDLE;
end
else if(!lt_framen) //只有等frame信号无效时,本地数据才真正的传输到PCI总线上去。
cstate <= READ_ZL5011x_1; //等待PCI总线把数据读完,以便进行下一此数据的读写。
else
begin
cpu_oe_n <= 1'b1;
cpu_cs_n <= 1'b1;
ot_count <= 8'b0;
ready_n <= 1'b1;
cstate <= IDLE;
end
end
WRITE_ZL5011x:
begin
//cpu_cs_n <= 1'b0;
cpu_we_n <= 1'b0; //本地能有效
cpu_ts_ale <= 1'b1; //地址锁存到本地端
cstate <= WRITE_ZL5011x_1;
end
WRITE_ZL5011x_1:
begin
cpu_ts_ale <= 1'b0;
ot_count <= ot_count + 1 ;
if(ot_count == ot_thr)
begin
ready_n <= 1'b1;
abort_n <=1'b0;
ot_count <= 8'b0;
OT_CNT <= OT_CNT + 1;
cstate <= IDLE;
end
else if(!lt_dxfrn) //等数据到local端,到了之后就交给本地端进行时序控制!
begin
ready_n <= 1'b1; //数据到了local端,那么不使能local端。
ot_count <= 8'b0;
cstate <= WRITE_ZL5011x_2;
end
else
begin
cstate <= WRITE_ZL5011x_1;
end
end
WRITE_ZL5011x_2:
begin
ot_count <= ot_count + 1 ;
if(ot_count == ot_thr)
begin
abort_n <=1'b0;
ot_count <= 8'b0;
OT_CNT <= OT_CNT + 1;
ready_n <= 1'b1;
cstate <= IDLE;
end
else if(!cpu_ta_n) //数据已经到了local端,等待本地端有效接收
begin
cpu_we_n <= 1'b1; //本地接收到数据之后,就禁止再写入数据。
ot_count <= 8'b0;
cstate <= WRITE_ZL5011x_3;
end
else
begin
cstate <= WRITE_ZL5011x_2;
end
end
WRITE_ZL5011x_3: //数据已经处理完了,恢复到空闲状态!
begin
cpu_cs_n <= 1'b1;
ready_n <= 1'b1;
cstate <= IDLE;
end
RTC_RD:
begin
rtc_counter <= rtc_counter + 1'b1;
if(rtc_counter == 1) begin
rtc_ad_out_reg <= addr_in[7:0];
rtc_as <= 1'b1;
rtc_cs_n <= 1'b0;
rtc_ad_oe <= 1'b1; end
else if(rtc_counter == 3) begin
rtc_as <= 1'b0; end
else if(rtc_counter == 6) begin
rtc_ds <= 1'b0;
rtc_ad_oe <= 1'b0; end
else if(rtc_counter == 9) begin
ready_n <= 1'b0;
rtc_ad_ie <= 1'b1; end
else if(rtc_counter == 11) begin
ready_n <= 1'b1;
rtc_ad_ie <= 1'b0;
rtc_ds <= 1'b1; end
else if(rtc_counter == 12) begin
rtc_cs_n <= 1'b1;
cstate <= IDLE; end
else begin
cstate <= RTC_RD; end
end
RTC_WR:
begin
rtc_counter <= rtc_counter + 1'b1;
if(rtc_counter == 1) begin
rtc_ad_out_reg <= addr_in[7:0];
rtc_as <= 1'b1;
rtc_cs_n <= 1'b0;
rtc_ad_oe <= 1'b1; end
else if(rtc_counter == 3) begin
ready_n <= 1'b1;
rtc_as <= 1'b0; end
else if(rtc_counter == 6) begin
rtc_ad_out_reg <= pi_data_reg[7:0];
rtc_rw <= 1'b0; end
else if(rtc_counter == 11) begin
rtc_cs_n <= 1'b1;
rtc_rw <= 1'b1; end
else if(rtc_counter == 12) begin
rtc_ad_out_reg <= 8'h0;
rtc_ad_oe <= 1'b0;
cstate <= IDLE; end
else begin
cstate <= RTC_WR; end
end
/* READ_PMC4351:
begin
// frame_ale <= 1'b0;
// frame_cs_n <= 1'b0;
// frame_rd_n <= 1'b0;
ot_count <= ot_count + 1 ;
if(ot_count == 8'b00000001)/*wait 80ns 便于读的数据有效*/
/* begin
ready_n <= 1'b0;
ot_count <= 8'b0;
cstate <= READ_PMC4351_1;
end
else
cstate <= READ_PMC4351;
end
READ_PMC4351_1:
begin
ot_count <= ot_count + 1 ;
if(ot_count == `ot_thr)
begin
abort_n <= 1'b0;
ot_count <= 8'b0;
OT_CNT <= OT_CNT + 1;
ready_n <= 1'b1;
cstate <= IDLE;
end
else if(!lt_framen)
cstate <= READ_PMC4351_1;
else
begin
frame_cs_n <= 1'b1;
frame_rd_n <= 1'b1;
ot_count <= 8'b0;
ready_n <= 1'b1;
cstate <= IDLE;
end
end
WRITE_PMC4351:
begin
// frame_ale <= 1'b0;
// frame_cs_n <= 1'b0;
// frame_wr_n <= 1'b0;
ot_count <= ot_count + 1 ;
if(ot_count == `ot_thr)
begin
ready_n <= 1'b1;
abort_n <=1'b0;
ot_count <= 8'b0;
OT_CNT <= OT_CNT + 1;
cstate <= IDLE;
end
else if(!lt_dxfrn) //数据已经到了local端,并且直接到了本度端。
begin
ready_n <= 1'b1;
ot_count <= 8'b0;
cstate <= WRITE_PMC4351_1;
end
else
begin
cstate <= WRITE_PMC4351;
end
end
WRITE_PMC4351_1:
begin
frame_cs_n <= 1'b1;
frame_wr_n <= 1'b1;
ready_n <= 1'b1;
cstate <= IDLE;
end
READ_ep1c3:
begin
ot_count <= ot_count + 1 ;
if(ot_count == 8'b00000010)/*wait 60ns*/
/* begin
ot_count <= 8'b0;
ready_n <= 1'b0;
cstate <= READ_ep1c3_1;
end
else
cstate <= READ_ep1c3;
end
READ_ep1c3_1:
begin
ot_count <= ot_count + 1 ;
if(ot_count == `ot_thr)
begin
abort_n <= 1'b0;
ot_count <= 8'b0;
OT_CNT <= OT_CNT + 1;
ready_n <= 1'b1;
cstate <= IDLE;
end
else if(!lt_framen)
cstate <= READ_ep1c3_1;
else
begin
sig_cs_n <= 1'b1;
sig_wr_n <= 1'b1;
sig_oe <= 1'b1;
ot_count <= 8'b0;
ready_n <= 1'b1;
cstate <= IDLE;
end
end
WRITE_ep1c3:
begin
ot_count <= ot_count + 1 ;
if(ot_count == `ot_thr)
begin
ready_n <= 1'b1;
abort_n <=1'b0;
ot_count <= 8'b0;
OT_CNT <= OT_CNT + 1;
cstate <= IDLE;
end
else if(!lt_dxfrn)
begin
sig_cs_n <= 1'b1;
ready_n <= 1'b1;
ot_count <= 8'b0;
cstate <= WRITE_ep1c3_1;
end
else
cstate <= WRITE_ep1c3;
end
WRITE_ep1c3_1:
begin
ot_count <= ot_count + 1 ;
if(ot_count == 8'b00000011)/*wait 90ns*/
/* begin
ot_count <= 8'b0;
sig_cs_n <= 1'b1;
sig_wr_n <= 1'b1;
sig_oe <= 1'b1;
ready_n <= 1'b1;
cstate <= IDLE;
end
else
cstate <= WRITE_ep1c3_1;
end */
default: cstate <= IDLE;
endcase
end
end
/******************************************************************************/
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -