Preface
- Bus protocolsupporting slave module is prepared. Pair with master.
- Request enters FIFO and is divided into R/W and afterwards accesses internal memory. Read Data is temporarily returned to master side after receiving by FIFO. Different from master, burst length can be specified shorter as required.
- Internal memory is not initialized hence, Read from parts where there is no Write will be Unknown. Matching the convenience of this test module, will initialize for higher modules.
- As slave operation, like SRAM data is processed with the shortest latency. When a delayed model is required, need to create a block signal internally against gnt or ack(Currently do not support.)
Sample code
/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2012, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
// ***************************** MODULE HEADER *********************************
module slave (
req, gnt, rxw, burst, addr,
wrStrb, wrAck, wrData, wrMask,
rdStrb, rdAck, rdData,
reset, clk
);
// ************************ PARAMETER DECLARATIONS *****************************
// Bus word length and burst length, set according to target
parameter NLR = 2; // Word Length Radix
parameter BLR = 2; // Burst Length Radix
parameter NL = 1<<NLR;
parameter NBL = 8<<NLR;
parameter BL = 1<<BLR;
// ***************************** I/O DECLARATIONS ******************************
// Request bus, burst length(burst) specify within BLR range
output req;
input gnt;
output rxw;
input [BLR-1:0] burst;
output [31:0] addr;
// Write Data Bus
output wrStrb;
input wrAck;
output [NBL-1:0] wrData;
output [NL-1:0] wrMask;
// Read Data Bus
output rdStrb;
input rdAck;
input [NBL-1:0] rdData;
input reset;
input clk;
// ************************** LOCAL DECLARATIONS *******************************
reg [32+BLR:0] aFIFO[0:31];
reg aBusy, aFull;
wire aBusyD, aFullD;
wire iAlloc;
reg [5:0] iaPtr, oaPtr;
wire [5:0] iaPtrD, oaPtrD;
wire oRxw;
wire [BLR-1:0] oBurst;
wire [31:0] oAddr;
wire oAlloc;
reg [BLR-1:0] oCnt;
wire oDone;
wire [BLR-1:0] oMod;
reg [NBL-1:0] wdFIFO[0:127];
reg [NL-1:0] wmFIFO[0:127];
reg wBusy, wFull;
wire wBusyD, wFullD;
reg [7:0] iwPtr, owPtr;
wire [7:0] iwPtrD, owPtrD;
wire iwAlloc;
wire irAlloc;
wire [NBL-1:0] owData;
wire [NL-1:0] owMask;
reg [BL*NBL-1:0] mask;
wire owAlloc;
reg [NBL-11:0] rdFIFO[0:127];
reg rBusy, rFull;
wire rBusyD, rFullD;
reg [7:0] irPtr, orPtr;
wire [7:0] irPtrD, orPtrD;
wire orAlloc;
reg [BL*NBL-1:0] mem[0:'h10_0000-1];
integer i, j;
// ******************************** MODULE BODY ********************************
// -----------------------------------------------------------------------------
// Req
always @(posedge clk)
if (iAlloc)
aFIFO[iaPtr[4:0]] <= #1 {rxw, burst, addr};
always @(posedge clk)
if (reset) begin
aBusy <= #1 1'b0;
aFull <= #1 1'b0;
iaPtr <= #1 6'h00;
oaPtr <= #1 6'h00;
end
else begin
aBusy <= #1 aBusyD;
aFull <= #1 aFullD;
iaPtr <= #1 iaPtrD;
oaPtr <= #1 oaPtrD;
end
assign aFullD = (iaPtrD[5] != oaPtrD[5]) & (iaPtrD[4:0] == oaPtrD[4:0]);
assign aBusyD = (iaPtrD != oaPtrD);
assign iaPtrD = iaPtr + iAlloc;
assign oaPtrD = oaPtr + (oAlloc & oDone);
assign iAlloc = req & gnt;
assign {oRxw, oBurst, oAddr}
= aFIFO[oaPtr[4:0]];
assign oAlloc = aBusy & (oRxw ? !rFull : wBusy);
assign gnt = !aFull;
// -----------------------------------------------------------------------------
// Req Information
always @(posedge clk)
if (reset)
oCnt <= #1 'h0;
else if (oAlloc)
oCnt <= #1 oDone ? 'h0 : oCnt + 'h1;
assign oDone = (oCnt == oBurst);
assign oMod = oCnt + oAddr[BLR+1:2];
// -----------------------------------------------------------------------------
// Write Data
always @(posedge clk)
if (iwAlloc) begin
wdFIFO[iwPtr[6:0]] <= #1 wrData;
wmFIFO[iwPtr[6:0]] <= #1 wrMask;
end
always @(posedge clk)
if (reset) begin
wFull <= #1 1'b0;
wBusy <= #1 1'b0;
iwPtr <= #1 8'h00;
owPtr <= #1 8'h00;
end
else begin
wFull <= #1 wFullD;
wBusy <= #1 wBusyD;
iwPtr <= #1 iwPtrD;
owPtr <= #1 owPtrD;
end
assign wFullD = (iwPtrD[7] != owPtrD[7]) & (iwPtrD[6:0] == owPtrD[6:0]);
assign wBusyD = (iwPtrD != owPtrD);
assign iwPtrD = iwPtr + iwAlloc;
assign owPtrD = owPtr + owAlloc;
assign iwAlloc = wrStrb & wrAck;
assign wrAck = !wFull;
// -----------------------------------------------------------------------------
// Read Data
assign rdAck = rBusy;
assign rdData = rdFIFO[irPtr[6:0]];
assign irAlloc = rdStrb & rdAck;
// -----------------------------------------------------------------------------
// Memory Write
always @(posedge clk)
if (owAlloc)
mem[oAddr[31:BLR+NLR]]
<= #1 {BL{owData}} & ~mask | mem[oAddr[31:BLR+NLR]] & mask;
always @(
owMask or
oMod
)
for (i=0; i<BL; i=i+1)
for (j=0; j<NBL; j=j+1)
mask[NL*i+j] = owMask[j/8] | (oMod[i] != i);
assign owData = wdFIFO[owPtr[6:0]];
assign owMask = wmFIFO[owPtr[6:0]];
assign owAlloc = aBusy & !oRxw & wBusy;
// -----------------------------------------------------------------------------
// Memory Read
always @(posedge clk)
if (orAlloc)
rdFIFO[orPtr[6:0]]
<= #1 mem[oAddr[31:BLR+NLR]] >> {oMod, {NLR+3{1'b0}}};
always @(posedge clk)
if (reset) begin
rFull <= #1 1'b0;
rBusy <= #1 1'b0;
irPtr <= #1 8'h00;
orPtr <= #1 8'h00;
end
else begin
rFull <= #1 rFullD;
rBusy <= #1 rBusyD;
irPtr <= #1 irPtrD;
orPtr <= #1 orPtrD;
end
assign rFullD = (irPtrD[7] != orPtrD[7]) & (irPtrD[6:0] == orPtrD[6:0]);
assign rBusyD = (irPtrD != orPtrD);
assign irPtrD = irPtr + irAlloc;
assign orPtrD = orPtr + orAlloc;
assign orAlloc = aBusy & !rFull & oRxw;
// **************************** FUNCTIONS and TASKS ****************************
endmodule
// *****************************************************************************
Logical Circuit Design > Test > Bus Slave Next page(SRAM Model) TOP of this page ▲