我认识的AHB2APB桥
一、代码
AHB总线代码见我认识的AHB - Holybanban - 博客园
1.1 AHB2APB桥的接口
module ahb2apb1 #(
parameter ADDR_WIDTH = 32 ,
parameter DATA_WIDTH = 32
)(
//system
input wire PCLK ,
input wire PRESETn ,
//apb slave
output wire [ADDR_WIDTH-1:0] PADDR ,
output wire PSEL1 ,
output wire PSEL2 ,
output wire PENABLE ,
output wire PWRITE ,
output wire [DATA_WIDTH-1:0] PWDATA ,
input wire PREADYIN1 ,
input wire PREADYIN2 ,
input wire [DATA_WIDTH-1:0] PRDATAIN1 ,
input wire [DATA_WIDTH-1:0] PRDATAIN2 ,
//ahb master
input wire HSELx ,
input wire [ADDR_WIDTH-1:0] HADDR ,
input wire [1:0] HTRANS ,
input wire HWRITE ,
input wire [2:0] HSIZE ,
input wire [2:0] HBURST ,
input wire [DATA_WIDTH-1:0] HWDATA ,
output wire [DATA_WIDTH-1:0] PRDATAOUT ,
output wire PREADYOUT
`ifdef RARELY_USED_SIGNAL
output wire [2:0] PPROT ,
output wire PNSE ,
output wire [DATA_WIDTH/8-1:0] PSTRB ,
output wire PWAKEUP ,
output wire [31:0] PAUSER ,
output wire [DATA_WIDTH/2-1:0] PWUSER ,
input wire PSLVERR ,
input wire [DATA_WIDTH/2-1:0] PRUSER ,
input wire [31:0] PBUSER
`endif
);
1.2 AHB2APB1
目前只能适配AHB的Single读写传输,后续会加入AHB2APB2,作为AHB总线的第二个桥从机。
`timescale 1ns/1ps
/*
* Address Space
* subordinate1 0x0000_0000~0x0000_ffff
* subordinate2 0x0001_0000~0x0001_ffff
*/
module ahb2apb1 #(
parameter ADDR_WIDTH = 32 ,
parameter DATA_WIDTH = 32
)(
//system
input wire PCLK ,
input wire PRESETn ,
//apb slave
output wire [ADDR_WIDTH-1:0] PADDR ,
output wire PSEL1 ,
output wire PSEL2 ,
output wire PENABLE ,
output wire PWRITE ,
output wire [DATA_WIDTH-1:0] PWDATA ,
input wire PREADYIN1 ,
input wire PREADYIN2 ,
input wire [DATA_WIDTH-1:0] PRDATAIN1 ,
input wire [DATA_WIDTH-1:0] PRDATAIN2 ,
//ahb master
input wire HSELx ,
input wire [ADDR_WIDTH-1:0] HADDR ,
input wire [1:0] HTRANS ,
input wire HWRITE ,
input wire [2:0] HSIZE ,
input wire [2:0] HBURST ,
input wire [DATA_WIDTH-1:0] HWDATA ,
output wire [DATA_WIDTH-1:0] PRDATAOUT ,
output wire PREADYOUT
`ifdef RARELY_USED_SIGNAL
output wire [2:0] PPROT ,
output wire PNSE ,
output wire [DATA_WIDTH/8-1:0] PSTRB ,
output wire PWAKEUP ,
output wire [31:0] PAUSER ,
output wire [DATA_WIDTH/2-1:0] PWUSER ,
input wire PSLVERR ,
input wire [DATA_WIDTH/2-1:0] PRUSER ,
input wire [31:0] PBUSER
`endif
);
localparam IDLE = 2'b00;
localparam SETUP = 2'b01;
localparam ACCESS = 2'b10;
localparam BUSY = 2'b01;
localparam NONSEQ = 2'b10;
localparam SEQ = 2'b11;
/*********************************************************/
reg [ADDR_WIDTH-1:0] haddr_d;
reg hwrite_d;
always @(posedge PCLK or negedge PRESETn) if(!PRESETn) #1 haddr_d <= 32'd0; else #1 haddr_d <= HADDR;
always @(posedge PCLK or negedge PRESETn) if(!PRESETn) #1 hwrite_d <= 1'b0; else #1 hwrite_d <= HWRITE;
reg [ADDR_WIDTH-1:0] paddr_d;
reg pwrite_d;
reg [DATA_WIDTH-1:0] pwdata_d;
always @(posedge PCLK or negedge PRESETn) if(!PRESETn) #1 paddr_d <= 32'd0; else #1 paddr_d <= PADDR;
always @(posedge PCLK or negedge PRESETn) if(!PRESETn) #1 pwrite_d <= 1'b0; else #1 pwrite_d <= PWRITE;
always @(posedge PCLK or negedge PRESETn) if(!PRESETn) #1 pwdata_d <= 32'd0; else #1 pwdata_d <= PWDATA;
/*********************************************************/
reg [1:0] state;
reg [1:0] nextstate;
always @(*) begin
case(state)
IDLE: if(HTRANS == NONSEQ && PREADYOUT && HSELx) nextstate = SETUP;
else nextstate = IDLE;
SETUP: nextstate = ACCESS;
ACCESS: if(HTRANS == IDLE && PREADYOUT) nextstate = IDLE;
else nextstate = ACCESS;
default: nextstate = IDLE;
endcase
end
always @(posedge PCLK or negedge PRESETn) if(!PRESETn) #1 state <= IDLE; else #1 state <= nextstate;
/*********************************************************/
wire preadyin = ({PSEL2, PSEL1} == 2'b01) ? PREADYIN1 :
({PSEL2, PSEL1} == 2'b10) ? PREADYIN2 : 1'b1;
wire [DATA_WIDTH-1:0] prdatain = ({PSEL2, PSEL1} == 2'b01) ? PRDATAIN1 :
({PSEL2, PSEL1} == 2'b10) ? PRDATAIN2 : 32'd0;
/*********************************************************/
assign PADDR = (state == SETUP) ? haddr_d : paddr_d;
assign PSEL1 = (state == IDLE) ? 1'b0 :
(PADDR[31:16] == 16'h0000) ? 1'b1 : 1'b0;
assign PSEL2 = (state == IDLE) ? 1'b0 :
(PADDR[31:16] == 16'h0001) ? 1'b1 : 1'b0;
assign PWRITE = (state == SETUP) ? hwrite_d : pwrite_d;
assign PWDATA = (state == SETUP) ? HWDATA : pwdata_d;
assign PENABLE = (state == ACCESS);
assign PREADYOUT = (state == IDLE) ? 1'b1 :
(state == SETUP) ? 1'b0 : preadyin;
assign PRDATAOUT = (state == ACCESS && !PWRITE) ? prdatain : 32'd0;
endmodule
1.3 Subordinate1
作为APB1总线的从机1,有3个等待周期
`timescale 1ns/1ps
module subordinate1 #(
parameter DATA_WIDTH = 32 ,
parameter ADDR_WIDTH = 32
)(
input wire PCLK ,
input wire PRESETn ,
input wire [ADDR_WIDTH-1:0] PADDR ,
input wire PSELx ,
input wire PENABLE ,
input wire PWRITE ,
input wire [DATA_WIDTH-1:0] PWDATA ,
output wire PREADYOUT ,
output wire [DATA_WIDTH-1:0] PRDATAOUT
);
localparam IDLE = 3'b000;
localparam STAGE1 = 3'b001;
localparam STAGE2 = 3'b010;
localparam STAGE3 = 3'b011;
localparam STAGE4 = 3'b100;
reg [2:0] state;
reg [2:0] nextstate;
always @(*) begin
case(state)
IDLE: if(PSELx) nextstate = STAGE1;
else nextstate = IDLE;
STAGE1: nextstate = STAGE2;
STAGE2: nextstate = STAGE3;
STAGE3: nextstate = STAGE4;
STAGE4: nextstate = IDLE;
default: nextstate = IDLE;
endcase
end
always @(posedge PCLK or negedge PRESETn) if(!PRESETn) #1 state <= IDLE; else #1 state <= nextstate;
reg [DATA_WIDTH-1:0] reg0; //addr = 0
reg [DATA_WIDTH-1:0] reg1; //addr = 4
reg [DATA_WIDTH-1:0] reg2; //addr = 8
reg [DATA_WIDTH-1:0] reg3; //addr = c
reg [DATA_WIDTH-1:0] reg4; //addr = 10
reg [DATA_WIDTH-1:0] reg5; //addr = 14
reg [DATA_WIDTH-1:0] reg6; //addr = 18
reg [DATA_WIDTH-1:0] reg7; //addr = 1c
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg0 <= 32'd0;
else if(state == STAGE4 && PWRITE && PADDR[15:0] == 16'h0) #1 reg0 <= PWDATA;
else #1 reg0 <= reg0;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg1 <= 32'd0;
else if(state == STAGE4 && PWRITE && PADDR[15:0] == 16'h4) #1 reg1 <= PWDATA;
else #1 reg1 <= reg1;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg2 <= 32'd0;
else if(state == STAGE4 && PWRITE && PADDR[15:0] == 16'h8) #1 reg2 <= PWDATA;
else #1 reg2 <= reg2;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg3 <= 32'd0;
else if(state == STAGE4 && PWRITE && PADDR[15:0] == 16'hc) #1 reg3 <= PWDATA;
else #1 reg3 <= reg3;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg4 <= 32'd0;
else if(state == STAGE4 && PWRITE && PADDR[15:0] == 16'h10) #1 reg4 <= PWDATA;
else #1 reg4 <= reg4;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg5 <= 32'd0;
else if(state == STAGE4 && PWRITE && PADDR[15:0] == 16'h14) #1 reg5 <= PWDATA;
else #1 reg5 <= reg5;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg6 <= 32'd0;
else if(state == STAGE4 && PWRITE && PADDR[15:0] == 16'h18) #1 reg6 <= PWDATA;
else #1 reg6 <= reg6;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg7 <= 32'd0;
else if(state == STAGE4 && PWRITE && PADDR[15:0] == 16'h1c) #1 reg7 <= PWDATA;
else #1 reg7 <= reg7;
end
assign PRDATAOUT = (state == STAGE4 && !PWRITE && PADDR[15:0] == 16'h0) ? reg0 :
(state == STAGE4 && !PWRITE && PADDR[15:0] == 16'h4) ? reg1 :
(state == STAGE4 && !PWRITE && PADDR[15:0] == 16'h8) ? reg2 :
(state == STAGE4 && !PWRITE && PADDR[15:0] == 16'hc) ? reg3 :
(state == STAGE4 && !PWRITE && PADDR[15:0] == 16'h10) ? reg4 :
(state == STAGE4 && !PWRITE && PADDR[15:0] == 16'h14) ? reg5 :
(state == STAGE4 && !PWRITE && PADDR[15:0] == 16'h18) ? reg6 :
(state == STAGE4 && !PWRITE && PADDR[15:0] == 16'h1c) ? reg7 : 32'd0;
assign PREADYOUT = (state == IDLE || state == STAGE4);
endmodule
1.4 Subordinate2
作为APB1总线的从机2,无等待周期
`timescale 1ns/1ps
module subordinate2 #(
parameter DATA_WIDTH = 32 ,
parameter ADDR_WIDTH = 32
)(
input wire PCLK ,
input wire PRESETn ,
input wire [ADDR_WIDTH-1:0] PADDR ,
input wire PSELx ,
input wire PENABLE ,
input wire PWRITE ,
input wire [DATA_WIDTH-1:0] PWDATA ,
output wire PREADYOUT ,
output wire [DATA_WIDTH-1:0] PRDATAOUT
);
localparam IDLE = 3'b000;
localparam STAGE1 = 3'b001;
reg [2:0] state;
reg [2:0] nextstate;
always @(*) begin
case(state)
IDLE: if(PSELx) nextstate = STAGE1;
else nextstate = IDLE;
STAGE1: nextstate = IDLE;
default: nextstate = IDLE;
endcase
end
always @(posedge PCLK or negedge PRESETn) if(!PRESETn) #1 state <= IDLE; else #1 state <= nextstate;
reg [DATA_WIDTH-1:0] reg0; //addr = 0
reg [DATA_WIDTH-1:0] reg1; //addr = 4
reg [DATA_WIDTH-1:0] reg2; //addr = 8
reg [DATA_WIDTH-1:0] reg3; //addr = c
reg [DATA_WIDTH-1:0] reg4; //addr = 10
reg [DATA_WIDTH-1:0] reg5; //addr = 14
reg [DATA_WIDTH-1:0] reg6; //addr = 18
reg [DATA_WIDTH-1:0] reg7; //addr = 1c
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg0 <= 32'd0;
else if(state == STAGE1 && PWRITE && PADDR[15:0] == 16'h0) #1 reg0 <= PWDATA;
else #1 reg0 <= reg0;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg1 <= 32'd0;
else if(state == STAGE1 && PWRITE && PADDR[15:0] == 16'h4) #1 reg1 <= PWDATA;
else #1 reg1 <= reg1;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg2 <= 32'd0;
else if(state == STAGE1 && PWRITE && PADDR[15:0] == 16'h8) #1 reg2 <= PWDATA;
else #1 reg2 <= reg2;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg3 <= 32'd0;
else if(state == STAGE1 && PWRITE && PADDR[15:0] == 16'hc) #1 reg3 <= PWDATA;
else #1 reg3 <= reg3;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg4 <= 32'd0;
else if(state == STAGE1 && PWRITE && PADDR[15:0] == 16'h10) #1 reg4 <= PWDATA;
else #1 reg4 <= reg4;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg5 <= 32'd0;
else if(state == STAGE1 && PWRITE && PADDR[15:0] == 16'h14) #1 reg5 <= PWDATA;
else #1 reg5 <= reg5;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg6 <= 32'd0;
else if(state == STAGE1 && PWRITE && PADDR[15:0] == 16'h18) #1 reg6 <= PWDATA;
else #1 reg6 <= reg6;
end
always @(posedge PCLK or negedge PRESETn) begin
if(!PRESETn) #1 reg7 <= 32'd0;
else if(state == STAGE1 && PWRITE && PADDR[15:0] == 16'h1c) #1 reg7 <= PWDATA;
else #1 reg7 <= reg7;
end
assign PRDATAOUT = (state == STAGE1 && !PWRITE && PADDR[15:0] == 16'h0) ? reg0 :
(state == STAGE1 && !PWRITE && PADDR[15:0] == 16'h4) ? reg1 :
(state == STAGE1 && !PWRITE && PADDR[15:0] == 16'h8) ? reg2 :
(state == STAGE1 && !PWRITE && PADDR[15:0] == 16'hc) ? reg3 :
(state == STAGE1 && !PWRITE && PADDR[15:0] == 16'h10) ? reg4 :
(state == STAGE1 && !PWRITE && PADDR[15:0] == 16'h14) ? reg5 :
(state == STAGE1 && !PWRITE && PADDR[15:0] == 16'h18) ? reg6 :
(state == STAGE1 && !PWRITE && PADDR[15:0] == 16'h1c) ? reg7 : 32'd0;
assign PREADYOUT = (state == IDLE || state == STAGE1);
endmodule
1.5 Decoder
`timescale 1ns/1ps
module decoder #(
parameter ADDR_WIDTH = 32
)(
input wire [ADDR_WIDTH-1:0] HADDR ,
output wire HSEL1 ,
output wire HSEL2 ,
output wire HSELD
);
/*
* Address Space
* ahb2apb1 0x0000_0000~0x0001_ffff 64KB
* ahb2apb2 0x0002_0000~0x0003_ffff 64KB
*/
reg hsel1;
reg hsel2;
reg hseld;
always @(*) begin
case(HADDR[31:16])
16'h0000, 16'h0001:
{hseld, hsel2, hsel1} = 3'b001;
16'h0002, 16'h0003:
{hseld, hsel2, hsel1} = 3'b010;
default:
{hseld, hsel2, hsel1} = 3'b100;
endcase
end
assign HSEL1 = hsel1;
assign HSEL2 = hsel2;
assign HSELD = hseld;
endmodule
1.6 Testbench
`timescale 1ns/1ps
module testbench;
localparam DATA_WIDTH = 32;
localparam ADDR_WIDTH = 32;
//size
localparam BYTE = 3'd0;
localparam HALFWORD = 3'd1;
localparam WORD = 3'd2;
//burst
localparam SINGLE = 3'd0;
localparam INCR = 3'd1;
localparam WRAP4 = 3'd2;
localparam INCR4 = 3'd3;
localparam WRAP8 = 3'd4;
localparam INCR8 = 3'd5;
localparam WRAP16 = 3'd6;
localparam INCR16 = 3'd7;
//ahb
reg HCLK ;
reg HRESETn ;
wire [ADDR_WIDTH-1:0] HADDR ;
wire [2:0] HBURST ;
wire [2:0] HSIZE ;
wire [1:0] HTRANS ;
wire [DATA_WIDTH-1:0] HWDATA ;
wire HWRITE ;
reg cmd_start ;
reg [DATA_WIDTH-1:0] cmd_wdata ;
reg [ADDR_WIDTH-1:0] cmd_addr ;
reg cmd_write ;
reg [2:0] cmd_size ;
reg [2:0] cmd_burst ;
reg [3:0] cmd_length ;
reg cmd_busy ;
reg cmd_stop ;
wire [DATA_WIDTH-1:0] cmd_rdata ;
wire cmd_error ;
wire cmd_ready ;
//decoder
wire HSEL1 ;
wire HSEL2 ;
//ahb2apb1
wire [ADDR_WIDTH-1:0] PADDR ;
wire PSEL1 ;
wire PSEL2 ;
wire PENABLE ;
wire PWRITE ;
wire [DATA_WIDTH-1:0] PWDATA ;
wire [DATA_WIDTH-1:0] PRDATAOUT1 ;
wire PREADYOUT1 ;
//sub1
wire S_PREADYOUT1;
wire [DATA_WIDTH-1:0] S_PRDATAOUT1;
//sub2
wire S_PREADYOUT2;
wire [DATA_WIDTH-1:0] S_PRDATAOUT2;
//multiplexor
reg [DATA_WIDTH-1:0] HRDATA ;
reg HREADY ;
//rstn_sync
wire HRESETn_s ;
rstn_sync u_rstn_sync(
.clk_i (HCLK) ,
.rstn_async_i (HRESETn) ,
.rstn_sync_o (HRESETn_s)
);
ahb #(
.DATA_WIDTH (DATA_WIDTH) ,
.ADDR_WIDTH (ADDR_WIDTH)
)u_ahb(
.HCLK (HCLK) ,
.HRESETn (HRESETn_s) ,
.HADDR (HADDR) ,
.HBURST (HBURST) ,
.HSIZE (HSIZE) ,
.HTRANS (HTRANS) ,
.HWDATA (HWDATA) ,
.HWRITE (HWRITE) ,
.HRDATA (HRDATA) ,
.HREADY (HREADY) ,
.HRESP () ,
.cmd_start (cmd_start) ,
.cmd_wdata (cmd_wdata) ,
.cmd_addr (cmd_addr) ,
.cmd_write (cmd_write) ,
.cmd_size (cmd_size) ,
.cmd_burst (cmd_burst) ,
.cmd_length (cmd_length) ,
.cmd_busy (cmd_busy) ,
.cmd_stop (cmd_stop) ,
.cmd_rdata (cmd_rdata) ,
.cmd_error (cmd_error) ,
.cmd_ready (cmd_ready)
);
decoder #(
.ADDR_WIDTH (ADDR_WIDTH)
)u_decoder(
.HADDR (HADDR) ,
.HSEL1 (HSEL1) ,
.HSEL2 (HSEL2) ,
.HSELD ()
);
ahb2apb1 #(
.DATA_WIDTH (DATA_WIDTH) ,
.ADDR_WIDTH (ADDR_WIDTH)
)u_ahb2apb1(
.PCLK (HCLK) ,
.PRESETn (HRESETn_s) ,
.PADDR (PADDR) ,
.PSEL1 (PSEL1) ,
.PSEL2 (PSEL2) ,
.PENABLE (PENABLE) ,
.PWRITE (PWRITE) ,
.PWDATA (PWDATA) ,
.PREADYIN1 (S_PREADYOUT1) ,
.PREADYIN2 (S_PREADYOUT2) ,
.PRDATAIN1 (S_PRDATAOUT1) ,
.PRDATAIN2 (S_PRDATAOUT2) ,
.HSELx (HSEL1) ,
.HADDR (HADDR) ,
.HTRANS (HTRANS) ,
.HWRITE (HWRITE) ,
.HSIZE (HSIZE) ,
.HBURST (HBURST) ,
.HWDATA (HWDATA) ,
.PRDATAOUT (PRDATAOUT1) ,
.PREADYOUT (PREADYOUT1)
);
subordinate1 #(
.DATA_WIDTH (DATA_WIDTH) ,
.ADDR_WIDTH (ADDR_WIDTH)
)u_subordinate1(
.PCLK (HCLK) ,
.PRESETn (HRESETn_s) ,
.PADDR (PADDR) ,
.PSELx (PSEL1) ,
.PENABLE (PENABLE) ,
.PWRITE (PWRITE) ,
.PWDATA (PWDATA) ,
.PREADYOUT (S_PREADYOUT1) ,
.PRDATAOUT (S_PRDATAOUT1)
);
subordinate2 #(
.DATA_WIDTH (DATA_WIDTH) ,
.ADDR_WIDTH (ADDR_WIDTH)
)u_subordinate2(
.PCLK (HCLK) ,
.PRESETn (HRESETn_s) ,
.PADDR (PADDR) ,
.PSELx (PSEL2) ,
.PENABLE (PENABLE) ,
.PWRITE (PWRITE) ,
.PWDATA (PWDATA) ,
.PREADYOUT (S_PREADYOUT2) ,
.PRDATAOUT (S_PRDATAOUT2)
);
multiplexor #(
.DATA_WIDTH (DATA_WIDTH)
)u_multiplexor(
.HCLK (HCLK) ,
.HRESETn (HRESETn_s) ,
.HSEL1 (HSEL1) ,
.HSEL2 (HSEL2) ,
.HSELD () ,
.HREADYIN1 (PREADYOUT1) ,
.HRDATAIN1 (PRDATAOUT1) ,
.HRESPIN1 () ,
.HREADYIN2 () ,
.HRDATAIN2 () ,
.HRESPIN2 () ,
.HREADYIND () ,
.HRDATAIND () ,
.HRESPIND () ,
.HRDATAOUT (HRDATA) ,
.HREADYOUT (HREADY) ,
.HRESPOUT ()
);
initial begin
$fsdbDumpfile("ahb2apb.fsdb");
$fsdbDumpvars(0, testbench);
end
parameter TIMEOUT = 100000;
always #10 HCLK = ~HCLK;
initial begin
HCLK = 1'b0;
HRESETn = 1'b1;
cmd_start = 1'b0;
cmd_wdata = 'd0;
cmd_addr = 'd0;
cmd_write = 1'b0;
cmd_size = 3'd0;
cmd_burst = 3'd0;
cmd_length = 4'd0;
cmd_stop = 1'b0;
cmd_busy = 1'b0;
#55 HRESETn = 1'b0;
#50 HRESETn = 1'b1;
fork begin
#(TIMEOUT);
$finish(2);
end join_none
repeat(10) @(posedge HCLK);
Single_Write(32'h0000_0000, 32'd100);
Single_Write(32'h0001_0000, 32'd200);
Single_Read(32'h0000_0000);
Single_Read(32'h0001_0000);
//Single_Read(32'h0001_0000);
/*case2(32'h0000_0000, 32'd0);
case2(32'h0001_0000, 32'd0);
case3(32'h0000_0000);
case3(32'h0001_0000);*/
/*case4(32'h0000_001c, WRAP8);
case5(32'h0000_0004, WRAP8);
case4(32'h0001_0014, WRAP8);
case5(32'h0001_0008, WRAP4);*/
repeat(10) @(posedge HCLK);
$finish;
end
task Single_Write(input [ADDR_WIDTH-1:0] addr, input [DATA_WIDTH-1:0] data); //Single write
@(posedge HCLK) #1;
cmd_start = 1'b1;
@(posedge HCLK) #1;
cmd_start = 1'b0;
cmd_size = WORD;
cmd_burst = SINGLE;
cmd_write = 1;
cmd_addr = addr;
@(posedge HCLK) #1;
cmd_wdata = data;
cmd_size = $urandom();
cmd_burst = $urandom();
cmd_write = $urandom();
cmd_addr = $urandom();
@(posedge HCLK) #1;
cmd_wdata = $urandom();
#1 wait(HREADY);
endtask
task Single_Read(input [ADDR_WIDTH-1:0] addr); //Single read
@(posedge HCLK) #1;
cmd_start = 1'b1;
@(posedge HCLK) #1;
cmd_start = 1'b0;
cmd_size = WORD;
cmd_burst = SINGLE;
cmd_write = 0;
cmd_addr = addr;
@(posedge HCLK) #1;
cmd_wdata = $urandom();
cmd_size = $urandom();
cmd_burst = $urandom();
cmd_write = $urandom();
cmd_addr = $urandom();
@(posedge HCLK) #1;
#1 wait(HREADY);
endtask
task case2(input [ADDR_WIDTH-1:0] addr, input [DATA_WIDTH-1:0] data);//Incr write
@(posedge HCLK) #1;
cmd_start = 1'b1;
@(posedge HCLK) #1;
cmd_start = 1'b0;
cmd_size = WORD;
cmd_burst = INCR;
cmd_write = 1;
cmd_addr = addr;
#1 wait(HREADY); //write reg0
@(posedge HCLK) #1;
cmd_wdata = $urandom();
#1 wait(HREADY); //write reg1
@(posedge HCLK) #1;
cmd_wdata = $urandom();
#1 wait(HREADY); //write reg2
@(posedge HCLK) #1;
cmd_wdata = $urandom();
#1 wait(HREADY); //write reg3
@(posedge HCLK) #1;
cmd_wdata = $urandom();
#1 wait(HREADY); //write reg4
@(posedge HCLK) #1;
cmd_wdata = $urandom();
#1 wait(HREADY); //write reg5
@(posedge HCLK) #1;
cmd_wdata = $urandom();
#1 wait(HREADY); //write reg6
@(posedge HCLK) #1;
cmd_wdata = $urandom();
#1 wait(HREADY); cmd_stop = 1'b1; //write reg7
@(posedge HCLK) #1;
cmd_stop = 1'b0;
cmd_wdata = $urandom();
#1 wait(HREADY);
endtask
task case3(input [ADDR_WIDTH-1:0] addr);//Incr read
@(posedge HCLK) #1;
cmd_start = 1'b1;
@(posedge HCLK) #1;
cmd_start = 1'b0;
cmd_size = WORD;
cmd_burst = INCR;
cmd_write = 0;
cmd_addr = addr;
#1 wait(HREADY); //read reg0
@(posedge HCLK) #1;
#1 wait(HREADY); //read reg1
@(posedge HCLK) #1;
#1 wait(HREADY); //read reg2
@(posedge HCLK) #1;
#1 wait(HREADY); //read reg3
@(posedge HCLK) #1;
#1 wait(HREADY); //read reg4
@(posedge HCLK) #1;
#1 wait(HREADY); //read reg5
@(posedge HCLK) #1;
#1 wait(HREADY); //read reg6
@(posedge HCLK) #1;
#1 wait(HREADY); cmd_stop = 1'b1; //read reg7
@(posedge HCLK) #1;
cmd_stop = 1'b0;
#1 wait(HREADY);
endtask
task case4(input [ADDR_WIDTH-1:0] addr, input [2:0] burst);//INCR4... write
@(posedge HCLK) #1;
cmd_start = 1'b1;
@(posedge HCLK) #1;
cmd_start = 1'b0;
cmd_size = WORD;
cmd_burst = burst;
cmd_write = 1;
cmd_addr = addr;
case(cmd_burst)
INCR4, WRAP4:
repeat(4) begin
#1 wait(HREADY);
@(posedge HCLK) #1;
cmd_wdata = $urandom();
end
INCR8, WRAP8:
repeat(8) begin
#1 wait(HREADY);
@(posedge HCLK) #1;
cmd_wdata = $urandom();
end
INCR16, WRAP16:
repeat(16) begin
#1 wait(HREADY);
@(posedge HCLK) #1;
cmd_wdata = $urandom();
end
endcase
#1 wait(HREADY);
endtask
task case5(input [ADDR_WIDTH-1:0] addr, input [2:0] burst);//INCR4... read
@(posedge HCLK) #1;
cmd_start = 1'b1;
@(posedge HCLK) #1;
cmd_start = 1'b0;
cmd_size = WORD;
cmd_burst = burst;
cmd_write = 0;
cmd_addr = addr;
case(cmd_burst)
INCR4, WRAP4:
repeat(4) begin
#1 wait(HREADY);
@(posedge HCLK) #1;
end
INCR8, WRAP8:
repeat(8) begin
#1 wait(HREADY);
@(posedge HCLK) #1;
end
INCR16, WRAP16:
repeat(16) begin
#1 wait(HREADY);
@(posedge HCLK) #1;
end
endcase
#1 wait(HREADY);
endtask
endmodule
二、仿真
2.1 Single Write和Single Read

浙公网安备 33010602011771号