⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parallel_interface.v

📁 pci转local bus总线的应用
💻 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 + -