构建一个HTTP2请求到AVS

一旦与Alexa的语音服务连接(AVS)是成功,你的客户会使用HTTP / 2编码的多部分消息的Alexa的沟通。从你的客户发送的事件,以及Alexa发送的指令,指定服务器或客户端应该采取行动。下面的图说明了一个识别事件发送到AVS。多部分消息是由两部分组成。第一,一个JSON格式的事件,第二,捕获的音频产品的麦克风。
这里写图片描述
HTTP2消息头

每次调用AVS需要以下消息头:

:method = {{verb}}
:scheme = https
:path = /{{API version}}/{{events or directives}}
authorization = Bearer {{access_token}}
content-type = multipart/form-data; boundary={{boundary_term}}

方法

AVS支持以下方法:

POST:对所有事件发送到AVS使用此方法

GET:获得使用指令建立的下降通道

方案

访问AVS API是HTTPS方案。

路径

所有事件使用下列路径:

:path = /v20160207/events

所以指令使用下列路径:

:path = /v20160207/directives

授权

当一个用户授权访问你的产品,登录亚马逊返回一个access_token用来授权。access_token必须包含在每个请求的头。

authorization = Bearer {{access_token}}

内容类型

内容类型描述包含在正文中的数据。这使得AVS妥善处理请求。boundary_term和不同部位的多方消息。在Alexa的话,JSON和二进制音频。

内容类型应该是multipart/form-data。你可以自由地决定自己的boundary_term。唯一的要求是,boundary_term一致使用,boundary_term不存在的数据。

content-type = multipart/form-data; boundary={{boundary_term}}

HTTP / 2多部分消息

AVS希望HTTP / 2编码的多部分消息。多部分消息是由一个或多个JSON格式的指令/事件及其关联的二进制音频附件(如果需要)。

JSON Headers

下面的headers是每个部分请求JSON部分要求:

Content-Disposition: form-data; name="metadata"
Content-Type: application/json; charset=UTF-8

JSON内容

所有的JSON格式的事件发送到AVS格式如下:

{
    "event":{
        "header": {
            "namespace": "{{STRING}}",
            "name": "{{STRING}}",
            "messageId": "{{STRING}}",
        },
        "payload": {
        }
    }
}

每个事件都有唯一的头和有效载荷。在事件头上,确定接口和事件命名空间和名称,是一种独特的标识符和messageId客户端必须发送每个请求.

二进制音频头

下面的Hearders是每个部分要求二进制音频附件要求:

Content-Disposition: form-data; name="audio"
Content-Type: application/octet-stream

二进制音频内容

这部分的多部分消息是二进制音频。唯一需要音频附件的事件是识别事件。

HTTP 2响应

AVS将两种类型的反应,你的客户。第一种类型,像是多部分消息的请求,由一个或多个JSON格式的指令和相关的二进制音频附件(如果需要)。第二类是例外。例外情况是不多的信息和返回到您的客户端时,出现错误。每个异常将包括错误代码和说明。

实例

例1:

这个例子显示了一个识别事件,它接收一个指令作为响应。
Request:

// Note: HTTP2 is a binary protocol and the payload is not human-readable. This is for illustrative purposes only.

:method = POST
:scheme = https
:path = /v20160207/events
authorization = Bearer foo-bar
content-type = multipart/form-data; boundary=this-is-a-boundary

--this-is-a-boundary
Content-Disposition: form-data; name="metadata"
Content-Type: application/json; charset=UTF-8

{
    "context": [
        {
            "header": {
                "namespace": "AudioPlayer",
                "name": "PlaybackState"
            },
            "payload": {
                "token": "abcd1234",
                "offsetInMilliseconds": 7000,
                "playerActivity": "PLAYING"
            }
        },
        {
            "header": {
                "namespace": "Alerts",
                "name": "AlertsState"
            },
            "payload": {
                "allAlerts": [
                    {
                        "token": "foo-bar",
                        "type": "ALARM",
                        "scheduledTime": "2015-10-30T22:34:51+00:00"
                    }
                ],
                "activeAlerts": [
                ]
            }
        },
        {
            "header": {
                "namespace": "Speaker",
                "name": "VolumeState"
            },
            "payload": {
                "volume": 25,
                "muted": false
            }
        },
        {
            "header": {
                "namespace": "SpeechSynthesizer",
                "name": "SpeechState"
            },
            "payload": {
                "token": "zxcv8523",
                "offsetInMilliseconds": 0,
                "playerActivity": "FINISHED"
            }
        }
    ],
    "event": {
        "header": {
            "namespace": "SpeechRecognizer",
            "name": "Recognize",
            "messageId": "messageId-123",
            "dialogRequestId": "dialogRequestId-321"
        },
        "payload": {
            "profile": "CLOSE_TALK",
            "format": "AUDIO_L16_RATE_16000_CHANNELS_1"
        }
    }
}

--this-is-a-boundary
Content-Disposition: form-data; name="audio"
Content-Type: application/octet-stream

{{binary audio attachment}}
--this-is-a-boundary--

Response



:status = 200
content-type = multipart/related; boundary=this-is-a-boundary; type="application/json"

--this-is-a-boundary
Content-Type: application/json; charset=UTF-8

{
    "directive": {
        "header": {
            "namespace": "SpeechSynthesizer",
            "name": "Speak",
            "messageId": "ewq-321",
            "dialogRequestId": "dialogRequestId-321"
        },
        "payload": {
            "url": "cid:1234",
            "format": "AUDIO_MPEG"
            "token": "kr17447380422"
        }
    }
}

--this-is-a-boundary
Content-Type: application/octet-stream
Content-ID: 1234

{{binary audio attachment}}
--this-is-a-boundary--

例2:

此示例显示一个识别事件,该事件接收一个指令指令和一个侦听指令作为响应。
Request

// Note: HTTP2 is a binary protocol and the payload is not human-readable. This is for illustrative purposes only.

:method = POST
:scheme = https
:path = /v20160207/events
authorization = Bearer foo-bar
content-type = multipart/form-data; boundary=this-is-a-boundary

--this-is-a-boundary
Content-Disposition: form-data; name="metadata"
Content-Type: application/json; charset=UTF-8

{
    "context": [
        {
            "header": {
                "namespace": "AudioPlayer",
                "name": "PlaybackState"
            },
            "payload": {
                "token": "1234",
                "offsetInMilliseconds": "15874",
                "playerActivity": "PLAYING"
            }
        },
        {
            "header": {
                "namespace": "Alerts",
                "name": "AlertsState"
            },
            "payload": {
                "allAlerts": [
                    {
                        "token": "foo-bar",
                        "type": "ALARM",
                        "scheduledTime": "2015-10-30T22:34:51+00:00"
                    }
                ],
                "activeAlerts": [
                ]
            }
        },
        {
            "header": {
                "namespace": "Speaker",
                "name": "VolumeState"
            },
            "payload": {
                "volume": 25,
                "muted": false
            }
        },
        {
            "header": {
                "namespace": "SpeechSynthesizer",
                "name": "SpeechState"
            },
            "payload": {
                "token": "zlkv8723",
                "offsetInMilliseconds": 0,
                "playerActivity": "FINISHED"
            }
        }
    ],
    "event": {
        "header": {
            "namespace": "SpeechRecognizer",
            "name": "Recognize",
            "messageId": "bnm-123",
            "dialogRequestId": "dialogRequestId-201"
        },
        "payload": {
            "profile": "CLOSE_TALK",
            "format": "AUDIO_L16_RATE_16000_CHANNELS_1",
        }
    }
}

--this-is-a-boundary
Content-Disposition: form-data; name="audio"
Content-Type: application/octet-stream

{{binary audio attachment}}
--this-is-a-boundary--

Response

status = 200
content-type = multipart/related; boundary=this-is-a-boundary; type="application/json"

--this-is-a-boundary
Content-Type: application/json; charset=UTF-8

{
    "directive": {
        "header": {
            "namespace": "SpeechSynthesizer",
            "name": "Speak",
            "messageId": "lkj-321",
            "dialogRequestId": "dialogRequestId-201"
        },
        "payload": {
            "url": "cid:1234",
            "format": "AUDIO_MPEG",
            "token": "sn2716057"
        }
    }
}

--this-is-a-boundary
Content-Type: application/octet-stream
Content-ID: 1234

{{binary audio attachment}}
--this-is-a-boundary

Content-Type: application/json; charset=UTF-8

{
    "directive": {
        "header": {
            "namespace": "SpeechRecognizer",
            "name": "ExpectSpeech",
            "messageId": "fyr-212",
            "dialogRequestId": "dialogRequestId-201"
        },
        "payload": {
            "timeoutInMilliseconds": 8000
        }
    }
}
--this-is-a-boundary--
<think>嗯,用户想要在简化版的Altera Avalon DMA控制器中加入某个功能,并生成完整的Verilog源码。首先,我需要明确用户具体想要添加什么功能,但根据上下文可能是指基本的数据传输功能。接下来,我应该回顾DMA控制器的基本结构,包括Avalon-MM总线接口、寄存器配置、状态机控制、FIFO缓冲和中断处理等部分。 用户可能不太熟悉Verilog的具体实现,所以需要分步骤解释。首先,确定要添加的功能,比如地址递增、块传输模式或中断生成。然后,设计寄存器映射,定义控制寄存器、源地址、目的地址、传输长度等。接着,实现Avalon-MM主接口和从接口,处理读写请求和总线仲裁。 状态机的设计是关键,需要处理空闲、读数据、写数据和完成状态。在Verilog中,使用case语句来管理状态转换。FIFO的实现需要正确处理数据的暂存,避免溢出或下溢。中断逻辑部分,当传输完成时触发中断信号,并在控制寄存器中设置状态位。 代码生成时要注意模块的端口声明,时钟和复位信号,寄存器配置,状态机转换,以及主从接口的逻辑。验证部分需要编写测试平台,模拟不同传输场景,检查功能正确性和时序是否符合预期。 用户可能需要了解如何将各个模块整合,确保接口信号正确连接,以及如何处理可能的错误情况,比如传输长度为零或地址未对齐。此外,还需考虑性能优化,如通过增大FIFO深度来提高吞吐量,或者添加错误检测机制。 最后,总结实现步骤,强调模块化设计和验证的重要性,确保用户能够逐步构建和测试DMA控制器,最终生成可靠的Verilog代码。</think>我将以结构化方式为您讲解如何为简化版Altera Avalon DMA控制器添加功能并生成Verilog源码: 1. 系统架构设计 - 总线接口:Avalon-MM Master/Slave - 核心模块:寄存器组、状态机、FIFO缓冲、中断控制器 - 新增功能:地址递增、块传输模式、中断生成 2. 寄存器映射设计(32位宽度) | 地址偏移 | 寄存器名称 | 功能描述 | |----------|-------------|-----------------------| | 0x00 | Control | 使能/中断使能/传输方向 | | 0x04 | Status | 忙标志/中断状态 | | 0x08 | SourceAddr | 源地址 | | 0x0C | DestAddr | 目标地址 | | 0x10 | TransferLen | 传输长度(单位:字) | 3. Verilog核心代码框架 ```verilog module avalon_dma ( input clk, input reset_n, // Avalon-MM Slave Interface input [3:0] avs_address, input avs_read, output [31:0] avs_readdata, input avs_write, input [31:0] avs_writedata, // Avalon-MM Master Interface output [31:0] avm_address, output avm_read, input [31:0] avm_readdata, output avm_write, output [31:0] avm_writedata, input avm_waitrequest, // Interrupt output irq ); // 寄存器定义 reg [31:0] control_reg; reg [31:0] status_reg; reg [31:0] source_addr; reg [31:0] dest_addr; reg [31:0] transfer_len; // 状态机定义 typedef enum { IDLE, READ_DATA, WRITE_DATA, DONE } state_t; reg [1:0] current_state, next_state; // FIFO定义 reg [31:0] data_fifo [0:7]; reg [2:0] wr_ptr, rd_ptr; // 主状态机转移逻辑 always @(posedge clk or negedge reset_n) begin if (!reset_n) begin current_state <= IDLE; end else begin current_state <= next_state; end end // 主控制逻辑 always @(*) begin case(current_state) IDLE: begin if (control_reg[0] && transfer_len != 0) next_state = READ_DATA; else next_state = IDLE; end READ_DATA: begin if (!avm_waitrequest) next_state = WRITE_DATA; else next_state = READ_DATA; end WRITE_DATA: begin if (!avm_waitrequest) begin if (transfer_len == 0) next_state = DONE; else next_state = READ_DATA; end else begin next_state = WRITE_DATA; end end DONE: begin status_reg[0] = 1'b0; status_reg[1] = 1'b1; next_state = IDLE; end endcase end // 总线接口处理 always @(posedge clk) begin if (avs_write) begin case(avs_address) 4'h0: control_reg <= avs_writedata; 4'h4: status_reg <= avs_writedata; 4'h8: source_addr <= avs_writedata; 4'hC: dest_addr <= avs_writedata; 4'h10: transfer_len <= avs_writedata; endcase end end // 中断生成 assign irq = status_reg[1] && control_reg[1]; // 主接口控制 assign avm_read = (current_state == READ_DATA); assign avm_write = (current_state == WRITE_DATA); assign avm_address = (current_state == READ_DATA) ? source_addr : dest_addr; assign avm_writedata = data_fifo[rd_ptr]; // 地址更新逻辑 always @(posedge clk) begin if (current_state == READ_DATA && !avm_waitrequest) begin source_addr <= source_addr + 4; transfer_len <= transfer_len - 1; end if (current_state == WRITE_DATA && !avm_waitrequest) begin dest_addr <= dest_addr + 4; end end endmodule ``` 4. 关键功能实现 - 状态机控制流:实现DMA传输的启动、数据读取、写入和完成状态转换 - 地址自动递增:每次传输后自动更新源/目标地址 - 中断生成机制:传输完成后触发中断信号 - 总线握手处理:正确处理avm_waitrequest信号 - 流控制:通过FIFO缓冲实现读写操作解耦 5. 验证要点 - 编写Testbench验证寄存器配置功能 - 测试不同传输长度(单次/块传输) - 验证地址递增正确性 - 测试中断触发条件 - 验证总线等待请求处理能力 - 压力测试:连续传输和随机间隔传输 建议开发流程: 1. 使用Quartus Prime创建工程 2. 添加时序约束(.sdc文件) 3. 编写SystemVerilog测试平台 4. 使用ModelSim进行功能仿真 5. 通过SignalTap进行硬件调试 6. 进行时序分析和优化 注意事项: - 根据实际需求调整FIFO深度 - 增加错误状态寄存器(地址对齐错误、溢出错误等) - 可扩展支持突发传输模式 - 添加DMA通道复用机制(多通道支持) - 考虑字节使能信号处理 这个实现版本已经包含基本DMA功能,可根据具体应用场景进一步扩展高级功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值