博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
简易APB4 slave实践
阅读量:6619 次
发布时间:2019-06-25

本文共 7503 字,大约阅读时间需要 25 分钟。

   一个简易的(不完整的)APB4 slave的可以没有PREADY和PSLVERR,这两个信号都被赋予常数,以及没有PPROT。

   两种不同类型的寄存器:

       图: 普通寄存器电路图

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

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

 

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

 interface spec:

寄存器表: 

 

 部分代码:

1 module apb4_slave #( 2  parameter ADDRWIDTH = 12) 3 ( 4     input     wire               PCLK, 5     input     wire               PRESETn, 6  7     input    wire                    PSEL, 8     input    wire[ADDRWIDTH -1:0]    PADDR, 9     input    wire                    PENABLE,10     input    wire                    PWRITE,11     input    wire[31:0]              PWDATA,12     input    wire[3:0]               PSTRB,13 14     input    wire[3:0]                ECOREVNUM,15     16     output    wire[31:0]              PRDATA,17     output    wire                    PREADY,18     output    wire                    PSLVERR19 );20 21   wire  [ADDRWIDTH-1:0]  reg_addr;22   wire             reg_read_en;23   wire             reg_write_en;24   wire  [3:0]          reg_byte_strobe;25   wire  [31:0]        reg_wdata;26   wire   [31:0]        reg_rdata;27 28 apb4_slave #(.ADDRWIDTH  (ADDRWIDTH))29   u_apb_slave_interface(30 .pclk        (PCLK),31 .presetn      (PRESETn),32 33 .psel        (PSEL),34 .paddr        (PADDR),35 .penable      (PENABLE),36 .pwrite       (PWRITE),37 .pwdata       (PWDATA),38 .pstrb       (PSTRB),39 40 .prdata       (PRDATA),41 .pready       (PREADY),42 .pslverr      (PSLVERR),43 44 .addr        (reg_addr),45 .read_en       (reg_read_en),46 .write_en      (reg_write_en),47 .byte_strobe    (reg_byte_strobe),48 .wdata        (reg_wdata),49 .tdata        (reg_rdata)50 51 );

 

 

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: data0always @(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]; endend// Data register: data1always @(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]; endend// Data register: data2always @(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]; endend// Data register: data3always @(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]; endend// 寄存器的读操作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}}; endcaseend endmodule

 

转载于:https://www.cnblogs.com/yiwenbo/p/10047063.html

你可能感兴趣的文章
Tensorflow在win10下的安装(CPU版本)
查看>>
一次优化记录
查看>>
cgroup代码浅析(2)
查看>>
会计的思考(42):会计如何转变为公司的内部财务顾问
查看>>
利用钥匙串,在应用里保存用户密码的方法
查看>>
python 装饰器
查看>>
[辟谣]下蹲猛起来眼前发黑是心脏衰竭的表现?别扯了!
查看>>
paper 96:计算机视觉-机器学习近年部分综述
查看>>
vuex状态管理详细使用方法
查看>>
不要等有了足够的钱才选择去创业!!!
查看>>
手把手教你画嘴巴,以后再也不怕画嘴巴了
查看>>
selenium - webdriver - 截图方法get_screenshot_as_file()
查看>>
io.lettuce.core.RedisCommandTimeoutException: Command timed out
查看>>
种子填充算法描述及C++代码实现
查看>>
Kali渗透测试——快速查找Metasploit的模块
查看>>
如何生成项目的chm文档
查看>>
java封装httpClient工具(支持http和https,包含get和post请求)
查看>>
Rocket - diplomacy - LazyModuleImpLike
查看>>
Exchange Server 2016管理系列课件25.管理安全通讯组
查看>>
计算机科学,大一学生怎样来爱你(文&PPT)
查看>>