amba apb simple testbench

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しているアクセスとなっています。

apb write

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

apb_read

コメント

Copied title and URL