はじめに
- バスプロトコルのチェッカーとして、マスターモジュールを用意しています。
- RequestとDataを生成するとともに、内部に用意したメモリもWriteで更新します。Read Dataと内部メモリの内容を期待値とした比較を行います。差分があればメッセージを出します。
- 内部メモリは初期化していないので、Writeしない部分のReadはUnkownになります。被テストモジュールに都合に合わせて、上位モジュールで初期化します。
サンプルコード
/* **************************** MODULE PREAMBLE ********************************
Copyright (c) 2012, ArchiTek
This document constitutes confidential and proprietary information
of ArchiTek. All rights reserved.
*/
// ***************************** MODULE HEADER *********************************
module master (
req, gnt, rxw, addr,
wrStrb, wrAck, wrFlush, wrData, wrMask,
rdStrb, rdAck, rdFlush, rdData,
omit,
reset, clk
);
// ************************ PARAMETER DECLARATIONS *****************************
// アドレスマスク、対象に合わせて設定
parameter PAM = 32'hffffffff;
// バスの語長とバースト長、対象に合わせて設定
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パス
output req;
input gnt;
output rxw;
output [31:0] addr;
// Write Dataパス
output wrStrb;
input wrAck;
input wrFlush;
output [NBL-1:0] wrData;
output [NL-1:0] wrMask;
// Read Dataパス
output rdStrb;
input rdAck;
input rdFlush;
input [NBL-1:0] rdData;
// 1でアクセス禁止
input omit;
input reset;
input clk;
// ************************** LOCAL DECLARATIONS *******************************
reg req;
reg rxw;
reg [31:0] addr;
reg [BL*NBL-1:0] wd;
reg [BL*NL-1:0] wm;
reg wrStrb;
reg [BLR-1:0] wrCnt;
wire wrDone;
wire wrAlloc = wrStrb & wrAck;
reg rdStrb;
reg [BLR-1:0] rdCnt;
wire rdDone;
wire rdAlloc = rdStrb & rdAck;
reg [10:0] iwPtr, owPtr;
wire [10:0] iwPtrD, owPtrD;
reg [31:0] waFIFO[0:1023];
reg [BL*NBL-1:0] wdFIFO[0:1023];
reg [BL*NL-1:0] wmFIFO[0:1023];
reg [10:0] irPtr, orPtr;
wire [10:0] irPtrD, orPtrD;
reg [31:0] raFIFO[0:1023];
reg [BL*NBL-1:0] rdFIFO[0:1023];
wire owAlloc = wrAlloc & wrDone;
wire [31:0] owAddr = waFIFO[owPtr[9:0]];
wire [BL*NBL-1:0] owData = wdFIFO[owPtr[9:0]];
wire [BL*NL-1:0] owMask = wmFIFO[owPtr[9:0]];
wire orAlloc = rdAlloc & rdDone;
wire [31:0] orAddr = raFIFO[orPtr[9:0]];
wire [BL*NBL-1:0] orData = rdFIFO[orPtr[9:0]];
wire [NBL-1:0] orExp;
wire alloc = req & gnt;
wire iwAlloc = alloc & !rxw;
wire irAlloc = alloc & rxw;
wire diff;
reg [BL*NBL-1:0] mem[0:'h10_0000-1];
wire [BL*NBL-1:0] mask = maskFunc(wm);
wire [BL*NBL-1:0] rdata = mem[addr[31:BLR+NLR]];
wire [BL*NBL-1:0] wdata = wd & ~mask | rdata & mask;
integer i;
// ******************************** MODULE BODY ********************************
// -----------------------------------------------------------------------------
// Req
always @(posedge clk)
if (reset)
req <= #1 1'b0;
else if (!req | gnt)
req <= #1 !omit &
$random &
notFullFunc(irPtrD, orPtrD) &
notFullFunc(iwPtrD, owPtrD);
always @(posedge clk)
if (reset) begin
rxw <= #1 1'b0;
addr <= #1 32'd0;
end
else if (!req | gnt) begin
rxw <= #1 $random;
// addr <= #1 (addr + (1<<BLR+NLR)) & PAM; // Marching
addr <= #1 $random & PAM;
end
always @(posedge clk)
if (reset) begin
iwPtr <= #1 11'd0;
owPtr <= #1 11'd0;
irPtr <= #1 11'd0;
orPtr <= #1 11'd0;
end
else begin
iwPtr <= #1 iwPtrD;
owPtr <= #1 owPtrD;
irPtr <= #1 irPtrD;
orPtr <= #1 orPtrD;
end
assign iwPtrD = iwPtr + iwAlloc;
assign owPtrD = owPtr + owAlloc;
assign irPtrD = irPtr + irAlloc;
assign orPtrD = orPtr + orAlloc;
// -----------------------------------------------------------------------------
// Write Signal Assert
// Strobe信号が不要なら、$randomの行は使わない
always @(posedge clk)
if (reset)
wrStrb <= #1 1'b0;
else
wrStrb <= #1 notEmptyFunc(iwPtrD, owPtrD);
// wrStrb <= #1 notEmptyFunc(iwPtrD, owPtrD) & $random;
always @(posedge clk)
for (i=0; i<BL*NBL; i=i+1)
wd[i] <= #1 $random;
always @(posedge clk)
wm <= #1 $random;
always @(posedge clk)
if (iwAlloc) begin
waFIFO[iwPtr[9:0]] <= #1 addr;
wdFIFO[iwPtr[9:0]] <= #1 wd;
wmFIFO[iwPtr[9:0]] <= #1 wm;
end
always @(posedge clk)
if (iwAlloc)
mem[addr[31:BLR+NLR]] <= #1 wdata;
always @(posedge clk)
if (reset)
wrCnt <= #1 {BLR{1'b0}};
else if (wrAlloc)
wrCnt <= #1 wrDone ? {BLR{1'b0}} : wrCnt + 'h1;
assign wrDone = &wrCnt | wrFlush;
assign wrData = selDataFunc(owData, wrCnt + owAddr[BLR+NLR-1:NLR]);
assign wrMask = selMaskFunc(owMask, wrCnt + owAddr[BLR+NLR-1:NLR]);
// -----------------------------------------------------------------------------
// Read Signal Assert
// Strobe信号が不要なら、$randomの行は使わない
always @(posedge clk)
if (reset)
rdStrb <= #1 1'b0;
else
rdStrb <= #1 notEmptyFunc(irPtrD, orPtrD);
// rdStrb <= #1 notEmptyFunc(irPtrD, orPtrD) & $random;
always @(posedge clk)
if (irAlloc) begin
raFIFO[irPtr[9:0]] <= #1 addr;
rdFIFO[irPtr[9:0]] <= #1 rdata;
end
always @(posedge clk)
if (reset)
rdCnt <= #1 {BLR{1'b0}};
else if (rdAlloc)
rdCnt <= #1 rdDone ? {BLR{1'b0}} : rdCnt + 'h1;
assign rdDone = &rdCnt | rdFlush;
assign orExp = selDataFunc(orData, rdCnt + orAddr[BLR+NLR-1:NLR]);
// -----------------------------------------------------------------------------
// Read Check
always @(posedge clk)
if (!reset)
if (diff | (diff === 1'bx))
$display("Read Error\t(%d): [%32x]\t%x\t(%x?)",
$stime, orAddr, rdData, orExp);
assign diff = rdAlloc & (rdData != orExp);
// **************************** FUNCTIONS and TASKS ****************************
function [BL*NBL-1:0] maskFunc;
input [BL*NL-1:0] mask;
integer i, j;
for (i=0; i<BL*NL; i=i+1)
for (j=0; j<8; j=j+1)
maskFunc[8*i+j] = mask[i];
endfunction
function [NBL-1:0] selDataFunc;
input [BL*NBL-1:0] data;
input [BLR-1:0] sel;
integer i;
for (i=0; i<NBL; i=i+1)
selDataFunc[i] = data[(sel<<NLR+3)+i];
endfunction
function [NL-1:0] selMaskFunc;
input [BL*BL-1:0] mask;
input [BLR-1:0] sel;
integer i;
for (i=0; i<NL; i=i+1)
selMaskFunc[i] = mask[(sel<<NLR)+i];
endfunction
function notEmptyFunc;
input [10:0] ip;
input [10:0] op;
notEmptyFunc = (ip != op);
endfunction
function notFullFunc;
input [10:0] ip;
input [10:0] op;
notFullFunc = (ip[10] == op[10])
| (ip[9:0] != op[9:0]);
endfunction
endmodule
// *****************************************************************************
回路デザイン > テスト > バスプロトコルマスター 次のページ(バススレーブ) このページのTOP ▲