APB_temp

图: 普通寄存器电路图

图: 带读写控制寄存器电路图

图:带读写控制寄存器时序图

 一般来讲,一个模块的interface到内部reg之间,需要的信号为地址信号addr,读写使能信号(分开),byte_strobe字节选通信号,读写数据信号(分开)。

module apb4_slave #(
 parameter ADDRWIDTH = 12)
(
input wire       PCLK, input wire       PRESETn, input wire PSEL, input wire[ADDRWIDTH -1:0] PADDR, input wire PENABLE, input wire PWRITE, input wire[31:0] PWDATA, input wire[3:0] PSTRB, input wire[3:0] ECOREVNUM, output wire[31:0] PRDATA, output wire PREADY, output wire PSLVERR
);
  wire  [ADDRWIDTH-1:0]  reg_addr;
  wire             reg_read_en;
  wire             reg_write_en;
  wire  [3:0]          reg_byte_strobe;
  wire  [31:0]        reg_wdata;
  wire   [31:0]        reg_rdata;
apb4_slave #(.ADDRWIDTH  (ADDRWIDTH))
  u_apb_slave_interface(
.pclk        (PCLK),
.presetn      (PRESETn),

.psel        (PSEL),
.paddr       (PADDR),
.penable      (PENABLE),
.pwrite       (PWRITE),
.pwdata       (PWDATA),
.pstrb       (PSTRB),

.prdata       (PRDATA),
.pready       (PREADY),
.pslverr      (PSLVERR),

.addr        (reg_addr),
.read_en       (reg_read_en),
.write_en      (reg_write_en),
.byte_strobe    (reg_byte_strobe),
.wdata        (reg_wdata),
.tdata        (reg_rdata)

);

 
u_apb_slave_interfacef #(
    parameter    ADDRWIDTH = 12)
(
    // IO declaration
    input    wire                pclk,
    input    wire                presetn,
    // apb interface input
    input    wire                psel,
    input    wire[ADDRWIDTH-1:0]    paddr,
    input    wire                penable,
    input    wire                pwite,
    input    wire[31:0]            pwdata,
    input    wire[3:0]            pstrb,
    // apb interface output
    output     wire[31:0]            prdata,
    output     wire                pready,
    // Register interface
    output    wire[ADDRWIDTH-1:0]    addr,
    output    wire                read_en,
    output    wire                write_en,
    output    wire[3:0]            byte_pstrb,
    output    wire[31:0]            wdata,
    output    wire[31:0]            rdata
);

assign     pready = 1'b1;
assign     pslverr = 1'b0;

assign    addr = paddr;
assign    read_en = psel & (~pwrite);                // 当pwrite为0,psel为1的时候,才读
assign    write_en = psel & (~penable) & pwrite;     // 在PCLK中,第一拍为psel有效,penable为低,第二拍才是psel和penable同时有效;

assign    byte_pstrb = pstrb;
assign    wdata = pwdata;
assign    prdata = rdata;
module apb4_slave_reg #(
    parameter    ADDRWIDTH = 12)
(
    input    wire                pclk,
    input    wire                presetn,

    input    wire[ADDRWIDTH-1:0]    addr,
    input    wire                read_en,
    input    wire                write_en,
    input    wire[3:0]            byte_pstrb,
    input    wire[31:0]            wdata,
    input    wire                ecorevnum,
    output    wire[31:0]            rdata

);

localparam ARM_CMSDK_APB4_EG_SLAVE_PID4    = 32'h00000004; //    12'hFD0;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID5    = 32'h00000000; //    12'hFD4;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID6    = 32'h00000000; //    12'hFD8;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID7    = 32'h00000000; //    12'hFDC;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID0    = 32'h00000019; //    12'hFE0;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID1    = 32'h000000B8; //    12'hFE4;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID2    = 32'h0000001B; //    12'hFE8;
localparam ARM_CMSDK_APB4_EG_SLAVE_PID3    = 32'h00000000; //    12'hFEC;

wire        [3:0]        wr_sel;

// 取地址的高10位出来,why?
// 地址是32为对其的,末尾都是0(0000)、4(0100)、8(1000)、C(1100)循环的,低两位都是一样的,只有高10位不一样
assign     wr_sel[0] = ((addr[(ADDRWIDTH-1):2]==10'b0000000000)&(write_en)) ? 1'b1: 1'b0;
assign     wr_sel[1] = ((addr[(ADDRWIDTH-1):2]==10'b0000000001)&(write_en)) ? 1'b1: 1'b0;
assign     wr_sel[2] = ((addr[(ADDRWIDTH-1):2]==10'b0000000010)&(write_en)) ? 1'b1: 1'b0;
assign     wr_sel[3] = ((addr[(ADDRWIDTH-1):2]==10'b0000000011)&(write_en)) ? 1'b1: 1'b0;
 
// write_en = psel & (~penable) & pwrite; 时序要求在penable为高这一拍把数据写下去,所以要在其前一拍判断是否要写。

// 寄存器的写操作
// Data register: data0
always @(posedge pclk or negedge presetn) begin
    if (~presetn) begin
        data0 <= {32{1'b0}};
    end 
    else if (wr_sel[0]) begin
        if (byte_strobe[0])
            data0[ 7:0] <= wdata[7:0];
        if (byte_strobe[1])
            data0[15:8] <= wdata[15:8];
        if (byte_strobe[2])
            data0[23:16] <= wdata[23:16];
        if (byte_strobe[3])
            data0[31:24] <= wdata[31:24];
    end
end
// Data register: data1
always @(posedge pclk or negedge presetn) begin
    if (~presetn) begin
        data1 <= {32{1'b0}};
    end 
    else if (wr_sel[1]) begin
        if (byte_strobe[0])
            data1[ 7:0] <= wdata[7:0];
        if (byte_strobe[1])
            data1[15:8] <= wdata[15:8];
        if (byte_strobe[2])
            data1[23:16] <= wdata[23:16];
        if (byte_strobe[3])
            data1[31:24] <= wdata[31:24];
    end
end
// Data register: data2
always @(posedge pclk or negedge presetn) begin
    if (~presetn) begin
        data2 <= {32{1'b0}};
    end 
    else if (wr_sel[2]) begin
        if (byte_strobe[0])
            data2[ 7:0] <= wdata[7:0];
        if (byte_strobe[1])
            data2[15:8] <= wdata[15:8];
        if (byte_strobe[2])
            data2[23:16] <= wdata[23:16];
        if (byte_strobe[3])
            data2[31:24] <= wdata[31:24];
    end
end
// Data register: data3
always @(posedge pclk or negedge presetn) begin
    if (~presetn) begin
        data3 <= {32{1'b0}};
    end 
    else if (wr_sel[1]) begin
        if (byte_strobe[0])
            data3[ 7:0] <= wdata[7:0];
        if (byte_strobe[1])
            data3[15:8] <= wdata[15:8];
        if (byte_strobe[2])
            data3[23:16] <= wdata[23:16];
        if (byte_strobe[3])
            data3[31:24] <= wdata[31:24];
    end
end

// 寄存器的读操作
always @(read_en or    addr or    data0 or data1 or data2 or data3 or ecorevnum) begin
    case (read_en)
    1'b1: begin 
        if (addr[11:4] == 8'h00) begin        // 判断为RW类型的寄存器
            case (addr[3:2])
                2'b00: rdata = data0;
                2'b01: rdata = data1;
                2'b10: rdata = data2;
                2'b11: rdata = data3;
                default: rdata = {32{1'bx}};
            endcase
        end
        else if (addr[11:6] == 6'h3F) begin     // 判断为RO类型的寄存器
            case(addr[5:2])
            4'b0100:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID4;
            4'b0101:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID5;
            4'b0110:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID6;
            4'b0111:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID7;
            4'b1000:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID0;
            4'b1001:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID1;
            4'b1010:rdata = ARM_CMSDK_APB4_EG_SLAVE_PID2;
            4'b1011:rdata = {ARM_CMSDK_APB4_EG_SLAVE_PID3[31:0],ecorevnum[3:0],4'h0};
            default: rdata = {32{1'bx}};
            endcase
        end 
        else begin
            rdata = {32{1'b0}};
        end 
    end
    1'b0: begin
        rdata = {32{1'b0}};
    end 
    default: rdata = {32{1'bx}};
    endcase
end 

endmodule

猜你喜欢

转载自www.cnblogs.com/yiwenbo/p/10047063.html