APB概要
DUT(検証対象)にapb slaveを用いた検証環境です。

検証対象(DUT:apb_slave.sv)
DUT(検証対象)の中身は内部にメモリを持つシンプルな構成にしています。
module apb_slave
(
input PCLK ,
input PRESETN,
input [31:0] PADDR ,
input PWRITE ,
input PSEL ,
input PENABLE,
input [31:0] PWDATA ,
output reg [31:0] PRDATA ,
output reg PREADY
);
reg [31:0] RAM [64];
reg [1:0] apb_state;
reg [1:0] SETUP = 0 ;
reg [1:0] W_ENABLE = 1 ;
reg [1:0] R_ENABLE = 2 ;
always @(negedge PRESETN or posedge PCLK) begin
if (!PRESETN) begin
apb_state <= 2'b00 ;
PRDATA <= 32'd0 ;
PREADY <= 1'b0 ;
end
else begin
case (apb_state)
SETUP : begin
PRDATA <= 0;
if (PSEL) begin
if (PWRITE) begin
apb_state <= W_ENABLE;
end
else begin
apb_state <= R_ENABLE;
end
end
end
W_ENABLE : begin
if (PSEL && PWRITE) begin
RAM[PADDR] <= PWDATA;
PREADY <= #1 1;
end
apb_state <= SETUP;
end
R_ENABLE : begin
if (PSEL && !PWRITE) begin
PREADY <= 1;
PRDATA <= #1 RAM[PADDR];
end
apb_state <= SETUP;
end
default: begin
apb_state <= SETUP ;
PREADY <= #1 1'b0 ;
PRDATA <= #1 32'dx ;
end
endcase
end
end
endmodule
テストベンチ(tb.sv)
テストベンチはt_apb_writeとt_apb_readという2つのライト/リード用タスクを作成しました。
module apb_tb ;
logic PCLK ;
logic PRESETN ;
logic [31:0] PADDR ;
logic [31:0] PWDATA ;
logic [31:0] PRDATA ;
logic PSEL ;
logic PENABLE ;
logic PWRITE ;
logic PREADY ;
parameter STEP = 10 ;
logic [31:0] read_data ;
//Initialize
initial begin
PCLK = 1'b0 ;
PRESETN = 1'b1 ;
PSEL = 1'b0 ;
#(STEP*10)
PRESETN = 1'b0 ;
#(STEP*10)
PRESETN = 1'b1 ;
end
//CLOCK GENERATE
always #(STEP/2)
PCLK = ~PCLK ;
//APB INSTANSE
apb_slave apb (.PCLK(PCLK),
.PRESETN(PRESETN),
.PADDR(PADDR),
.PWDATA(PWDATA),
.PRDATA(PRDATA),
.PSEL(PSEL) ,
.PENABLE(PENABLE),
.PWRITE(PWRITE) ,
.PREADY(PREADY)
) ;
//WRITE TASK
task t_apb_write(logic [31:0] addr , logic [31:0] data) ;
@(posedge PCLK);
PSEL <= #1 1'b1 ;
PWRITE <= #1 1'b1 ;
PADDR <= #1 addr ;
PWDATA <= #1 data ;
@(posedge PCLK);
PENABLE<= #1 1'b1 ;
wait(PREADY);
@(posedge PCLK);
PSEL <= #1 1'b0 ;
PENABLE<= #1 1'b0 ;
endtask
//READ TASK
task t_apb_read(logic [31:0] addr) ;
@(posedge PCLK);
PSEL <= #1 1'b1 ;
PWRITE <= #1 1'b0 ;
PADDR <= #1 addr ;
@(posedge PCLK);
PENABLE<= #1 1'b1 ;
wait(PREADY) ;
read_data <= #1 PRDATA ;
@(posedge PCLK);
PSEL <= #1 1'b0 ;
PENABLE<= #1 1'b0 ;
endtask
//SCENARIO
initial begin
#(STEP*30);
t_apb_write(32'h0000_0000,32'h1234_5678) ;
t_apb_write(32'h0000_0004,32'hAAAA_BBBB) ;
#(STEP*10)
t_apb_read(32'h0000_0000) ;
t_apb_read(32'h0000_0004) ;
#(STEP*10)
$finish;
end
endmodule
これをVIVADOでシミュレーションしてみます。

実行される内容はtb.svに記載されている以下の部分です。アドレス0番地に32’h1234_5678を、アドレス4番地に32’hAAAA_BBBBをライトし、クロック10サイクル後にライトデータをリードします。
//SCENARIO
initial begin
#(STEP*30);
t_apb_write(32'h0000_0000,32'h1234_5678) ;
t_apb_write(32'h0000_0004,32'hAAAA_BBBB) ;
#(STEP*10)
t_apb_read(32'h0000_0000) ;
t_apb_read(32'h0000_0004) ;
end
「SIMULATION」の下の「Run Simulation」から「Run Behavioral Simulation」を実行します。
PREADYは1サイクルWAITしているアクセスとなっています。

リードを実行すると、ライトデータが読めることが確認できました。


コメント