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 + -
显示快捷键?