AHB到标准握手时序桥 - 逻辑设计部分
目录
- 1. HTRANS没法用
- 2. IDLE
- 3. 写
- 4. 读
- 5. 代码
AHB协议毕竟与FIFO、RAM等读写协议不一样,而AHB是SoC系统片内常用的高速接口,所以就需要将AHB的时序转化为标准的握手时序,例如下图
本文介绍整个设计的逻辑
从上图可以看出,AHB2HANDSHAKE模块是作为AHB slave出现的,所以要从AHB Slave角度进行设计。
依然是按照状态机的思路。如果是状态机的思路,AHB协议中HTRANS有四种状态、HBURST有八种状态,我们使用哪一个呢?还是自己写状态机?
可选择思路是基于HTRANS的IDLE、BUSY、NONSEQ和SEQ四种状态进行设计,毕竟burst传输属于NONSEQ或SEQ状态。
1. HTRANS没法用
哈哈哈我根据HTRANS的四种状态设计了半天发现作为AHB slave压根就没法用状态机。
先看看下面这几张波形图,从AHB Slave的角度思考一下
上图中揭示了AHB比较膈应的地方,就是一次访问地址和数据是分两拍进行的,当然这也是实现流水的基础。这就导致了第二拍传数据的时候,地址可以发生变化。
所以如果对一个地址的访问需要两拍,注意这两拍中address phase与data phase可不在同一个HTRANS,data phase甚至会跨越多个HTRANS状态。
换句话说就是,HTRANS这个状态机不能决定hwdata和hrdata信号的变化规律。
这个与平时的状态机设计不同,平时设计的思路是整个模块被分成好几个状态,该模块的每个信号会根据不同状态变化规律不一。
但是AHB协议中HADDR会根据HTRANS的取值来决定是否有效,而HWDATA和HRDATA的变化并不会参照HTRANS这个状态。
但是作为AHB Slave不必关心有没有跨HTRANS、HTRANS某个状态是否要延迟,这个是AHB Master要做的事情。作为slave,只需要将数据正确写入或正确读出即可
那么如何对AHB到标准握手时序桥进行设计呢?还是状态机,不过我们采用最原始的状态机:读和写
2. IDLE
该状态下当然是啥都不干啦,当检测到AHB master要进行传输时,即htrans为NONSEQ时,检测hwrite判断转入WRITE还是READ,如下图
于是状态机重写为
3. 写
该状态下实现写,当标准握手时序下写完成该状态结束。
注意是标准握手时序,所以需要将地址和数据在时序上对齐。
怎么实现呢?时序图在IDLE已经展现了,如下图带反压的WRITE
即便是burst写也可以
而WRITE下一个状态,则根据WRITE结束的那一拍htrans的值,状态机如下
关于那个BUSY作一下说明。AHB master在进入BUSY时会给出下一个传输的控制信号,但是在下一次传输真正来临时控制信号还会保持不变,所以在AHB slave检测到
wr_en && hready && (htrans == BUSY)
时依旧可以转换为IDLE状态
4. 读
该状态下实现读,当确定读出数据了该状态结束。
同样要求rd_en与rdata时序对齐,如果与写类似,将haddr打拍成raddr,那么在data phase第一拍必然不会读出数据,最快也要第二拍。
也就是说,必然会反压一拍,如下图带延迟的情况。
由此状态机更新为
5. 代码
module ahb2standard_handshake_bridge#(parameter HADDR_WIDTH = 32,parameter HDATA_WIDTH = 32parameter ACCESS_ADDR1 = 32'h0000_0000_0000_0010,parameter ACCESS_ADDR2 = 32'h0000_0000_0000_0014,parameter ACCESS_ADDR3 = 32'h0000_0000_0000_0018,parameter ACCESS_ADDR4 = 32'h0000_0000_0000_001C)(input hrstn,input hclk,input [HADDR_WIDTH-1:0] haddr,input [2:0] hburst,input [2:0] hsize,input [1:0] htrans,input hwrite,input hsel,input [HDATA_WIDTH-1:0] hwdata,output [HDATA_WIDTH-1:0] hrdata,output hready,output hresp,output [HADDR_WIDTH-1:0] waddr,output [HDATA_WIDTH-1:0] wdata,output wr_en,input wready,output [HADDR_WIDTH-1:0] raddr,input [HDATA_WIDTH-1:0] rdata,input rdata_val,output rd_en,input rready);localparam IDLE = 2'b00;
localparam WRITE = 2'b01;
localparam READ = 2'b11;reg [1:0] cur_state;
reg [1:0] nxt_state;
reg [HADDR_WIDTH-1:0] waddr_r;
reg [HADDR_WIDTH-1:0] raddr_r;
reg hready_r;
reg wr_en_r;
reg rd_en_r;
reg hresp_r;always@(posedge hclk or negedge hrstn) beginif(!hrstn)cur_state <= IDLE;elsecur_state <= nxt_state;
endalways@(*) begincase(cur_state)IDLE:if(htrans[1]) beginif(hwrite)nxt_state = WRITE;elsenxt_state = READ;endelsenxt_state = IDLE;WRITE:if(wr_en && hready) beginif(!htrans[1])nxt_state = IDLE;else if(!hwrite)nxt_state = READ;elsenxt_state = WRITE;endelsenxt_state = WRITE;READ:if(rdata_val) beginif(!htrans[1])nxt_state = IDLE;else if(hwrite)nxt_state = WRITE;elsenxt_state = READ;endelsenxt_state = READ;default:nxt_state = IDLE;endcase
endassign wdata = hwdata[(8 << hsize)-1:0];always@(*) begincase(cur_state)IDLE:hready_r = 1'b0;WRITE:hready_r = wready;READ:hready_r = rdata_val;default:hready_r = 1'b0;endcase
endassign hready = hready_r;always@(posedge hclk or negedge hrstn) beginif(!hrstn)waddr_r <= 'd0;else if(cur_state == IDLE) beginif(htrans[1] && hwrite)waddr_r <= haddr;endelse if(cur_state == WRITE) beginif(wr_en && hready && htrans[1] && hwrite)waddr_r <= haddr;endelse if(cur_state == READ) beginif(rdata_val && htrans[1] && hwrite)waddr_r <= haddr;end
endassign waddr = waddr_r;always@(posedge hclk or negedge hrstn) beginif(!hrstn)wr_en_r <= 1'b0;else if(cur_state == IDLE) beginif(htrans[1] && hwrite)wr_en_r <= 1'b1;endelse if(cur_state == WRITE) beginif(!hready)wr_en_r <= wr_en_r;else if(htrans[1]) beginif(hwrite)wr_en_r <= 1'b1;elsewr_en_r <= 1'b0;endelsewr_en_r <= 1'b0;endelse if(cur_state == READ) beginif(rdata_val && htrans[1] && hwrite)wr_en_r <= 1'b1;end
endassign wr_en = wr_en_r;assign hrdata = rdata[(8 << hsize)-1:0];always@(posedge hclk or negedge hrstn) beginif(!hrstn)raddr_r <= 'd0;else if(cur_state == IDLE) beginif(htrans[1] && !hwrite)raddr_r <= haddr;endelse if(cur_state == WRITE) beginif(wr_en && hready && htrans[1] && !hwrite)raddr_r <= haddr;endelse if(cur_state == READ) beginif(rdata_val && htrans[1] && !hwrite)raddr_r <= haddr;end
endassign raddr = raddr_r;always@(posedge hclk or negedge hrstn) beginif(!hrstn)rd_en_r <= 1'b0;else if(cur_state == IDLE) beginif(htrans[1] && !hwrite)rd_en_r <= 1'b1;endelse if(cur_state == WRITE) beginif(wr_en && hready && htrans[1] && !hwrite)rd_en_r <= 1'b1;endelse if(cur_state == READ) beginif(!rready)rd_en_r <= rd_en_r;else if(!rdata_val)rd_en_r <= 1'b0;else if(htrans[1]) beginif(hwrite)rd_en_r <= 1'b0;elserd_en_r <= 1'b1;endelserd_en_r <= 1'b0;endelse rd_en_r <= 1'b0;
endassign rd_en = rd_en_r;always@(*) beginif(cur_state == WRITE && wr_en && hready) beginif(waddr != ACCESS_ADDR1 && waddr != ACCESS_ADDR2&& waddr != ACCESS_ADDR3&& waddr != ACCESS_ADDR4)hresp_r = 1'b1;endelse if(cur_state == READ && rdata_val) beginif(raddr != ACCESS_ADDR1 && raddr != ACCESS_ADDR2&& raddr != ACCESS_ADDR3&& raddr != ACCESS_ADDR4)hresp_r = 1'b1;endelsehresp_r = 1'b0;
endassign hresp = hresp_r;endmodule
AHB到标准握手时序桥 - 逻辑设计部分相关推荐
- 手机APP开发之MIT Appinventor详细实战教程(十),标准登陆界面的逻辑设计和数据库的有效使用
目录 (一)APP功能介绍 (二)设计流程 (三)知识点 (四)问题 (五)总结 (一)APP功能介绍 今天我们来学习设计一个登录界面的APP,虽然界面有些简陋,但其内在的逻辑设计却并不简单.我们首先 ...
- 串行外设接口(Serial Peripheral Interface, SPI)逻辑设计部分 - spi_master
目录 1. baud_clk_gen 1.1. 代码 2. spi_master 2.1. IDLE:等待写入 2.2. WAIT_CS:等待选通 2.3. TRANS:传输 (CPOL ^ CPHA ...
- UART的RTL逻辑设计部分 - uart_tx
目录 1. IDLE:等待并数据到来 1.1. valid&ready 的Slave写握手 1.2. 异步FIFO 的Master读握手 2. TRANS:并串转换 2.1. 打包tx_dat ...
- FPGA逻辑设计回顾(10)DDR/DDR2/DDR3中的时序参数的含义
前言 本文首发自:FPGA逻辑设计回顾(10)DDR/DDR2/DDR3中的时序参数的含义 上篇文章:FPGA逻辑设计回顾(9)DDR的前世今生以及演变过程中的技术差异有提到,制造商会以一系列由破折号 ...
- 数字逻辑基础实验二—时序逻辑电路的设计
实验目的 (1)掌握中规模集成寄存器构成的时序逻辑电路的设计方法. (2)掌握中规模集成计数器设计N进制计数器的方法. (3)学会用时序功能器件构成综合型应用电路. 实验电路 图 2-1红绿灯电路 实 ...
- 计算机逻辑模块,常用时序逻辑电路模块 《计算机结构与 及逻辑设计》课件.ppt...
常用时序逻辑电路模块 <计算机结构与 及逻辑设计>课件.ppt * ② 用反馈清0法实现模6计数 Q3Q2Q1Q0 & 0000 0001 0010 0011 0100 0101 ...
- FPGA逻辑设计回顾(8)单比特信号的CDC处理方式之Toggle同步器
文章目录 前言 脉冲反馈展宽同步器技术补充说明 RTL代码 行为仿真 低电平脉冲的展宽处理 切换同步器的原理与实现 RTL实现 前言 本文首发自:FPGA逻辑设计回顾(8)单比特信号的CDC处理方式之 ...
- 数字逻辑计算机组成,数字逻辑设计与计算机组成pdf
数字逻辑设计与计算机组成 内容简介 本书从简单的数字逻辑电路设计基础开始,由浅入深,讲解组合逻辑和时序逻辑电路的设计技术.计算机组成的基本原理和计算机体系结构的相关概念,后深入探讨了现代计算机系统如何 ...
- 数字电路逻辑设计笔记(2):逻辑代数基础
数字电路逻辑设计笔记(2):逻辑代数基础 参考教材:<数字电路逻辑设计>欧阳星明 人民邮电出版社 参考教程: 中国大学MOOC 西安工业大学<数字电子技术基础> 文章目录 数字 ...
最新文章
- 英特尔:谁说深度学习已死?AI任务挑大梁的是CPU,不是GPU
- 手机影音第六天 自定义播放器页面的实现(按钮暂时未监听)
- 中断(interrupted()、isInterrupted())、Executor的中断
- Table.Rows.Remove(dr)和Table.Delete()的区别
- 【定时同步系列4】QPSK调制+OM定时(FFT实现及频域补偿)+信号分段处理+误码率曲线之MATLAB仿真(复信号模型)
- RocksDB事务实现TransactionDB分析
- 研讨会 | 知识工程与问答技术研讨会 (KEQA2018)
- windows功能_这 12 个好用 Windows 软件,让你也能用上 macOS 的独占功能
- 实时“头发-面部皮肤”分割与人脸肤色分类
- 轻量级日志系统Loki原理简介和使用
- 3.2 Lucene实战:一个简单的小程序
- .Net免费公开课视频+资料+源码+经典牛逼 汇总篇【持续更新】
- 【图像去噪】基于matlab GUI多种滤波器图像去噪【含Matlab源码 1778期】
- moodle重定向_用最简单的pythonGUI库PysimpleGUI 设计一款中丹学院Moodle课件下载器。...
- android自定义popwindow,Android应用开发Android 自定义PopWindow的简单使用
- struts2之拦截器详解
- syntax sugar 2
- 一步一步教你写股票走势图——分时图五(自定义标记)
- Seventh season fifteenth episode,Joey got a new brain??????
- 转不撞南墙不回头——树规总结