FPGA实现SWD接口协议

1 SWD 协议简介

   SWD的全称是The Serial Wire Debug Port(SW-DP),也就是串行调试端口,是ARM目前支持的两种调试端口之一,另一种是JTAG。SWD通信只需SWDIO、SWDCLK两根线;SWDIO为双向Data线,SWDCLK为时钟线。

2 SWD 读写操作流程

2.1 写操作流程

  写操作的流程包括以下:

(1)发送8bit操作命令;

(2)一个空转周期;

(3)接收3bit的ACK;

(4)一个空转周期;

(5)发送32bit的写数据;

(6)发送1bit写数据的奇偶校验值;

2.2 读操作流程

  读操作的流程包括以下:

(1)发送8bit操作命令;

(2)一个空转周期;

(3)接收3bit的ACK;

(4)接收32bit的读数据;

(5)接收1bit读数据的奇偶校验值;

(6)一个空转周期;

2.3 术语含义

Start 起始位,值为1
APnDP 指示访问调试端口是DP还是AP,0:DP,1:AP
RnW 指示当次访问是写操作还是读操作,0:写,1:读
A[2:3] 指示DP/AP寄存器地址的Addr[3:2]字段
Parity 前一个数据包的奇偶校验位
Stop 停止位,值为0
Park 暂存位,为了被目标设备读取为高,值为1
Trn 调转周期,用于SWDIO切换IO方向,默认调转周期是一个时钟周期
ACK[0:2] 3bit的目标设备返回主机的响应,ACK[0:2]=0b100:OK,ACK[0:2]=0b010:,ACK[0:2]=0b001:FAULT
WDATA[0:31] 32bit的主机到目标设备的写数据,LSB传输
RDATA[0:31] 32bit的目标设备到主机的读数据,LSB传输

 

3 SWD 操作时序

  从第2章的流程协议图看来,看似收发数据是上升沿切换,下降沿采样,但实际上并不是。从ARM Debug InterfaceArchitecture Specification ADIv6.0里查看得知,也就是上图标红位置。协议指出,SWD目标设备是在SWCLK的上升沿采样数据,也是在SWCLK的上升沿切换数据。那么反过来,主机需要在SWCLK的下降沿去切换数据,SWCLK的下降沿去采集数据。这里,不知道是否个人理解有误,一般正常的逻辑是主从机都是在同一个沿去切换数据/采集数据,而SWD协议给我感觉要另类一点。

3 FPGA实现逻辑

   从第2张的读写协议流程看来,读和写的完整通信流程都有6个步骤,但步骤并不完全一样。这样具有明确的流程性通信,显然在FPGA中,使用状态机来实现是最合适的。状态机的状态跳转如下:

  注意的是,若ACK接收不是OK指令,则需要多发送一个Trn周期才能结束当次通信请求。

  状态机的Verilog代码如下:

复制代码
// ----------------------------------State Machine---------------------------------//
always @(posedge i_clk)
begin
    if(!i_rst_n) 
        state <= IDLE;
    else 
        case(state)
            IDLE:
                if(data_req_vld)
                    state <= CMD;
                else
                    state <= state;
            CMD:
                if(cmd_send_done)
                    state <= TRN0;
                else 
                    state <= state;
            TRN0:
                if(div_clk_done)
                    state <= ACK;
                else
                    state <= state;
            ACK:
                if(ack_rcv_ok && ack_rcv_done && ~swd_send_cmd[2])     // Write Data -->Need to switch directions
                    state <= TRN1;
                else if(ack_rcv_ok && ack_rcv_done && swd_send_cmd[2]) // Read Data -->No need to switch directions
                    state <= DATA;
                else if(!ack_rcv_ok && ack_rcv_done)                   // Ack false --> stop flow
                    state <= TRN2;
                else
                    state <= state;
            TRN1:
                if(div_clk_done)
                    state <= DATA;
                else
                    state <= state;
            DATA:
                if(data_flow_done)
                    state <= PAR;
                else
                    state <= state;
            PAR:
                if(div_clk_done && ~swd_send_cmd[2])     // Write
                    state <= IDLE;
                else if(div_clk_done && swd_send_cmd[2]) // Read
                    state <= TRN2;
                else
                    state <= state;
            TRN2:
                if(div_clk_done)
                    state <= IDLE;
                else
                    state <= state;    
            default:state <= IDLE;
        endcase
end
View Code
复制代码

4 逻辑分析结果

4.1 读时序

4.2 写时序

 

posted @   KD_one  阅读(586)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示