dmacntrl.v

来自「VHDLVERILOG语言实现的CARDBUS的IP源码,已经实现现场应用」· Verilog 代码 · 共 454 行 · 第 1/2 页

V
454
字号

	// Instantiate address incrementers
	assign IncRdAdr = Mst_RdData_Valid;
	assign IncWrAdr = Mst_Xfer_D1 & Mst_WrMode;
	assign LdRdAdrCnt = (WrRdAdr & !Usr_CBE[0] & !Usr_CBE[1] & !Usr_CBE[2] & !Usr_CBE[3]);
	assign LdWrAdrCnt = (WrWrAdr & !Usr_CBE[0] & !Usr_CBE[1] & !Usr_CBE[2] & !Usr_CBE[3]);
	
	ucount30 RdAdrReg	(.CLR(PCI_reset),.CLK(PCI_clk),.EN(IncRdAdr),
			.LOAD(LdRdAdrCnt), .D(Usr_WrData[29:0]), .Q(Mst_RdAd[31:2]));
	
	ucount30 WrAdrReg	(.CLR(PCI_reset),.CLK(PCI_clk),.EN(IncWrAdr),
			.LOAD(LdWrAdrCnt), .D(Usr_WrData[29:0]),.Q(Mst_WrAd[31:2]));

	assign Mst_RdAd[1:0] = 2'h0;
	assign Mst_WrAd[1:0] = 2'h0;

	// Instantiate Down Counters for DMA Read and Write Count
	assign LdWrCnt = WrDMACnt & !Usr_CBE[0] & !Usr_CBE[1];
	assign LdRdCnt = WrDMACnt & !Usr_CBE[2] & !Usr_CBE[3];
	assign DecDMARdCnt = IncRdAdr;
	always @(posedge PCI_clk)
		DecDMAWrCnt <= Mst_WrData_Rdy && Mst_WrMode;
	
	dcount16 RdCntReg (.CLR(PCI_reset),.CLK(PCI_clk),.EN(DecDMARdCnt),
			.LOAD(LdRdCnt), .D(Usr_WrData[31:16]), .Q(DMARdCnt[15:0]));

	dcount16 WrCntReg (.CLR(PCI_reset),.CLK(PCI_clk),.EN(DecDMAWrCnt),
			.LOAD(LdWrCnt), .D(Usr_WrData[15:0]), .Q(DMAWrCnt[15:0]));

	assign DMACntReg = {DMARdCnt, DMAWrCnt};

	// DMA Control Status Register Write
	always @(posedge PCI_clk or posedge PCI_reset) begin
		if (PCI_reset) begin
			DMAWrEn <= 0;
			DMARdEn <= 0;
			DMAWrErr <= 0;
			DMARdErr <= 0;
			LocalEn <= 0;
			Mst_LatCntEn <= 0;
			Mst_RdCmd <= 4'b0001;  // 01 = Memory Read
			Mst_WrCmd <= 3'b011;
			Mst_RdBE_Sel <= 0;
			Mst_RdBE <= 4'b0000;
			Mst_WrBE <= 4'b0000;
			Mst_WrBE_Sel <= 0;
			Mst_Rd_Term_Sel <= 0;
			Mst_RdData_Sel <= 0;
			Mst_WrData_Sel <= 0;
			end
		else begin
			if (WrCtrl && !Usr_CBE[3]) begin
				Mst_LatCntEn <= Usr_WrData[31];
				LocalEn <= Usr_WrData[30];
				Mst_RdCmd <= Usr_WrData[29:26];
				DMARdErr <= Usr_WrData[25];
				DMARdEn <= Usr_WrData[24];
				end
			if (WrCtrl && !Usr_CBE[2]) begin
				Mst_Rd_Term_Sel <= Usr_WrData[23];
				Mst_RdBE_Sel <= Usr_WrData[22];
				Mst_RdBE <= Usr_WrData[21:18];
				Mst_WrBE[3:2] <= Usr_WrData[17:16];
				end
			if (WrCtrl && !Usr_CBE[1]) begin
				Mst_WrBE[1:0] <= Usr_WrData[15:14];
				Mst_WrBE_Sel <= Usr_WrData[13];
				Mst_WrCmd <= Usr_WrData[12:10];
				DMAWrErr <= Usr_WrData[9];
				DMAWrEn <= Usr_WrData[8];
				end
			if (WrCtrl && !Usr_CBE[0]) begin
				Mst_RdData_Sel <= Usr_WrData[7];
				Mst_WrData_Sel <= Usr_WrData[6];
				end
			if ((Mst_Tabort_Det || Mst_TTO_Det) && Mst_RdMode) begin
				DMARdEn <= 0;
				DMARdErr <= 1;
				end
			if (RdCnt0 && DMARdEn == 1) DMARdEn <= 0;
			if ((Mst_Tabort_Det || Mst_TTO_Det) && Mst_WrMode) begin
				DMAWrEn <= 0;
				DMAWrErr <= 1;
				end
			if (WrCnt0 && DMAWrEn == 1 && Mst_WrBurst_Done) DMAWrEn <= 0;
		end
	end

	assign DMACtrlStat = {Mst_LatCntEn, LocalEn, Mst_RdCmd[3:0], DMARdErr, DMARdEn,
						  Mst_Rd_Term_Sel, Mst_RdBE_Sel, Mst_RdBE[3:0], Mst_WrBE[3:2],
						  Mst_WrBE[1:0], Mst_WrBE_Sel, Mst_WrCmd[2:0], DMAWrErr, DMAWrEn,
						  8'h00};

	// Create read/write enable control for state machine
	assign	PCIWrEn = DMAWrEn && BusMstEn;
	assign	PCIRdEn = DMARdEn && BusMstEn;

	// Current Burst Count Decodes
	assign BCnt_eq_3 = (Burst_Cnt == 3);
	assign BCnt_eq_2 = (Burst_Cnt == 2);
	assign BCnt_eq_1 = (Burst_Cnt == 1);
	assign BCnt2_eq_1 = (Burst_Cnt2 == 1);

	// Check for end of DMA
	assign RdBCnt = (DMARdCnt > Burst_Length) ? Burst_Length : DMARdCnt[7:0];
	assign WrBCnt = (DMAWrCnt > Burst_Length) ? Burst_Length : DMAWrCnt[7:0];
		
	always @(posedge PCI_clk) begin
		if (RdBCnt == 0) RdCnt0 = 1;
		else RdCnt0 = 0;
		if (WrBCnt == 0) WrCnt0 = 1;
		else WrCnt0 = 0;
		end
												 
	// DMA State Machine
	always @(posedge PCI_clk or posedge PCI_reset)
		begin : StateEqns
		if (PCI_reset) begin
			DMASm <= idle;
			Mst_Burst_Req <= 1'b0;
			Mst_WrData_Valid <= 1'b0;
			Mst_RdBE_Load_Done <= 1'b0;
		end else begin
	        casex (DMASm)  // synthesis parallel_case

 				idle: begin
				    // Back end ready, software enabled, and >0 transfers remain
					if (PCIWrEn && !WrCnt0 && ((~Mst_WrData_Sel && WrRdy) || Mst_WrData_Sel))
							DMASm <= dma_wr;
					else if (PCIRdEn && !RdCnt0 && ((~Mst_RdData_Sel && RdRdy) || Mst_RdData_Sel))
							DMASm <= dma_rd;
				end

				dma_rd: begin
					// if 1 left, and the last transfer is seen on the PCI bus
					// go to read wait state to wait for the pipeline to clear
					if (Mst_RdBurst_Done || DMARdErr) begin
						Mst_Burst_Req <= 1'b0;
						Mst_RdBE_Load_Done <= 1'b0;
						DMASm <= dma_rd_wt;
					end else begin
						DMASm <= dma_rd;
						Mst_Burst_Req <= 1'b1;
					end

					// if in multi-BE mode master read
					if (Mst_RdBE_Sel & ~Mst_RdBE_Load_Done) begin
						if (BCnt2_eq_1 && Mst_WrData_Rdy) begin
							// all BEs are transferred to PCI core
							// set flag to remember "done"
							Mst_WrData_Valid <= 1'b0;
							Mst_RdBE_Load_Done <= 1'b1;
						end else begin
							// still more BEs left
							Mst_WrData_Valid <= 1'b1;
							Mst_RdBE_Load_Done <= 1'b0;
						end
					end
				end

				dma_rd_wt: begin
				    DMASm <= idle;
				end

				dma_wr: begin
					Mst_Burst_Req <= 1'b1;
					Mst_WrData_Valid <= 1'b1;
					if ((BCnt_eq_1  || LastWr) && Mst_WrData_Rdy) begin
						DMASm <= dma_wr_wt;
						Mst_WrData_Valid <= 1'b0;
					end
					else if (DMAWrErr) DMASm <= idle;
				end

				dma_wr_wt: begin
					//  if no error and pipeline is not empty
					//  stay in this state, otherwise go to idle
					if (!DMAWrErr && !Mst_WrBurst_Done) begin
						DMASm <= dma_wr_wt;
						Mst_Burst_Req <= 1;
					end else begin
						DMASm <= idle;
						Mst_Burst_Req <= 0;
					end
				end
				default: DMASm <= 5'bx;
	        endcase
		end
    end

	// DMA Burst Counter
	assign Init_BCnt = (DMASm[idle_bt] && WrRdy && PCIWrEn && !WrCnt0) ? WrBCnt : RdBCnt;
	assign Ld_BCnt = DMASm[idle_bt];
	assign Dec_BCnt = (DMASm[dma_rd_bt] & Mst_Xfer_D1) || (Mst_WrData_Rdy & Mst_WrMode);
	assign Dec_BCnt2 = DMASm[dma_rd_bt] & Mst_WrData_Rdy & Mst_RdBE_Sel;

	dcount8 BRSTCNTR ( .CLK(PCI_clk), .CLR(PCI_reset), .D(Init_BCnt), .EN(Dec_BCnt),
					.LOAD(Ld_BCnt), .Q(Burst_Cnt));

	dcount8 BRSTCNTR2 ( .CLK(PCI_clk), .CLR(PCI_reset), .D(Init_BCnt), .EN(Dec_BCnt2),
					.LOAD(Ld_BCnt), .Q(Burst_Cnt2));

	// DMA Burst State Machine Outputs
	assign Mst_One_Read = BCnt_eq_1 || (BCnt_eq_2 && Mst_Xfer_D1);
	assign Mst_Two_Reads = DMARdErr || (BCnt_eq_2 | (BCnt_eq_3 && Mst_Xfer_D1));
	assign Mst_RdMode = DMASm[dma_rd_bt] | DMASm[dma_rd_wt_bt];
	assign Mst_WrMode = DMASm[dma_wr_bt] | DMASm[dma_wr_wt_bt];

endmodule



module ucount30( CLK, CLR, D, EN, LOAD, Q );
	input CLK, CLR;
	input [29:0] D;
	input EN, LOAD;

	output [29:0] Q;
	reg [29:0] Q;

always @(posedge CLK or posedge CLR)
	if (CLR) Q <= 30'b0;
		else if (LOAD) Q <= D;
			else if (EN) Q <= Q + 1;

endmodule

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?