mirror of
https://github.com/WangXuan95/FPGA-DDR-SDRAM.git
synced 2025-01-30 02:32:53 +08:00
update
This commit is contained in:
parent
9bf35a21cd
commit
0ffcfda9c3
56
README.md
56
README.md
@ -6,16 +6,16 @@ FPGA DDR-SDRAM
|
||||
|
||||
# 简介
|
||||
|
||||
|-------------------------| |--------------|
|
||||
| | | |
|
||||
----->| 驱动时钟和复位 | | |
|
||||
| | | |
|
||||
------------| | DDR-SDRAM接口 |--------->| |
|
||||
| AXI4 | | | |
|
||||
AXI4 master |----------->| AXI4 slave | | |
|
||||
| | | | |
|
||||
------------| |-------------------------| |--------------|
|
||||
用户逻辑 DDR1 控制器 DDR1 芯片
|
||||
|------------------------------| |-----------|
|
||||
| | | |
|
||||
----->| driving clock and reset | | |
|
||||
| | | |
|
||||
------------| | DDR-SDRAM interface |--------->| |
|
||||
| AXI4 | | | |
|
||||
AXI4 master |-------->| AXI4 slave | | |
|
||||
| | | | |
|
||||
------------| |------------------------------| |-----------|
|
||||
用户逻辑 DDR1 控制器 DDR1 芯片
|
||||
|
||||
很多低端 FPGA 开发板使用 SDR-SDRAM 作为片外存储,而 DDR-SDRAM (DDR1) 比 SDR-SDRAM 容量更大,价格更低。且与SDR-SDRAM一样,DDR1也能使用低端FPGA的普通的IO管脚直接驱动。我编写了一个软核的 AXI4 接口的 DDR1 控制器。该控制器的特点有:
|
||||
|
||||
@ -80,7 +80,7 @@ FPGA DDR-SDRAM
|
||||
| :---: |
|
||||
| 图:FPGA + DDR1 测试板 |
|
||||
|
||||
原理图见 PCB/sch.pdf ,PCB制造文件见 PCB/gerber.zip ,在布局布线时,使用双层板即可,不需像 DDR2 以上的设计那样刻意注意等长和阻抗匹配,因为该电路工作频率为双边沿 75MHz,不是特别高,只需注意让FPGA与DDR距离尽量近,布线尽量短即可。比如我在布局时,把DDR1芯片放在了FPGA芯片正对的背面,从而保证布线都较短。
|
||||
该板子的原理图见 PCB/sch.pdf ,PCB制造文件见 PCB/gerber.zip 。它是个双层板,不需像 DDR2 、 DDR3 那样刻意注意等长和阻抗匹配,因为该电路工作频率为双边沿 75MHz,不是特别高,只需注意让FPGA与DDR距离尽量近,布线尽量短即可。比如我把DDR1芯片放在了FPGA芯片正对的背面,从而保证布线都较短。
|
||||
|
||||
该板子的设计在立创EDA中开放,见 [oshwhub.com/wangxuan/fpga-ddr-ce-shi-ban](https://oshwhub.com/wangxuan/fpga-ddr-ce-shi-ban)。
|
||||
|
||||
@ -122,28 +122,28 @@ module ddr_sdram_ctrl #(
|
||||
|
||||
## 模块接口:驱动时钟和复位
|
||||
|
||||
该模块需要一个时钟和一个复位进行驱动,如下:
|
||||
该模块需要一个驱动时钟和一个驱动复位,如下:
|
||||
|
||||
```Verilog
|
||||
input wire rstn_async,
|
||||
input wire clk,
|
||||
input wire drv_clk,
|
||||
```
|
||||
|
||||
rstn_async 是低电平复位信号,正常工作时应该置高。clk 是驱动时钟,频率是用户时钟的 4 倍。
|
||||
rstn_async 是低电平复位信号,正常工作时应该置高。drv_clk 是驱动时钟,频率是用户时钟的 4 倍。
|
||||
|
||||
模块开始工作前,rstn_async 信号应该置低,让模块复位,然后把 rstn_async 置高,解除复位。
|
||||
|
||||
## 时钟频率的选取
|
||||
|
||||
模块内将驱动时钟 clk 分频 4 倍产生 DDR1 时钟(ddr_ck_p/ddr_ck_n)和 AXI4 总线用户时钟(aclk)。本节讲述如何决定驱动时钟 clk 的频率。
|
||||
模块内将驱动时钟 drv_clk 分频 4 倍产生 DDR1 时钟(ddr_ck_p/ddr_ck_n)和 AXI4 总线用户时钟(clk)。本节讲述如何决定驱动时钟 drv_clk 的频率。
|
||||
|
||||
首先,时钟频率受限于 DDR1 芯片。考虑到所有的 DDR1 的接口频率至少为 75MHz ,则 clk 的下限是 75\*4=300MHz。
|
||||
首先,时钟频率受限于 DDR1 芯片。考虑到所有的 DDR1 的接口频率至少为 75MHz ,则 drv_clk 的下限是 75\*4=300MHz。
|
||||
|
||||
而 clk 的上限就也取决于 DDR1 的芯片型号,例如对于 MT46V64M8P-5B ,查芯片手册可知,-5B 后缀的 DDR1 在 CAS Latency (CL)=2 时最高时钟频率是 133MHz,则 clk 的上限是 133\*4=532MHz 。
|
||||
而 drv_clk 的上限就也取决于 DDR1 的芯片型号,例如对于 MT46V64M8P-5B ,查芯片手册可知,-5B 后缀的 DDR1 在 CAS Latency (CL)=2 时最高时钟频率是 133MHz,则 drv_clk 的上限是 133\*4=532MHz 。
|
||||
|
||||
> 注意:本控制器固定 CAS Latency (CL) = 2。
|
||||
|
||||
另外,时钟频率的上限还受限于 FPGA 的速度,太高的时钟频率容易导致时序不收敛。本设计充分考虑时序安全设计,大多数寄存器工作在频率较低用户时钟域;个别寄存器工作在用户时钟的 2 倍频率的时钟下,且输入端口的组合逻辑非常短;还有一个寄存器工作在高频的 clk 下,但输入端口直接来自于上一级的寄存器输出(没有组合逻辑)。因此,即使在速度级别很低的 EP4CE6E22C8N 上,在 300MHz 的驱动时钟下也能保证模块正确运行。在速度等级更高的 FPGA (例如 EP4CE22F17C6N)上,驱动时钟的频率可以更高(例如400MHz)。
|
||||
另外,时钟频率的上限还受限于 FPGA 的速度,太高的时钟频率容易导致时序不收敛。本设计充分考虑时序安全设计,大多数寄存器工作在频率较低 clk 时钟域;个别寄存器工作在 clk 时钟的 2 倍频率的时钟下,且输入端口的组合逻辑非常短;还有一个寄存器工作在高频的 drv_clk 下,但输入端口直接来自于上一级的寄存器输出(没有组合逻辑)。因此,即使在速度级别很低的 EP4CE6E22C8N 上,在 300MHz 的驱动时钟下也能保证模块正确运行。在速度等级更高的 FPGA (例如 EP4CE22F17C6N)上,驱动时钟的频率可以更高(例如400MHz)。
|
||||
|
||||
## 模块接口:DDR1接口
|
||||
|
||||
@ -172,11 +172,11 @@ rstn_async 是低电平复位信号,正常工作时应该置高。clk 是驱
|
||||
DDR1 控制器对外提供 AXI4 从接口(AXI4 slave)的时钟和复位信号,如下。AXI4 主机应该用它们作为自己的时钟和复位。
|
||||
|
||||
```Verilog
|
||||
output reg aresetn,
|
||||
output reg aclk,
|
||||
output reg rstn,
|
||||
output reg clk,
|
||||
```
|
||||
|
||||
以下是该模块的 AXI4 从接口,它们都与 aclk 时钟的上升沿同步,应该连接到 FPGA 内的的 AXI4 主机。
|
||||
以下是该模块的 AXI4 从接口,它们都与 clk 时钟的上升沿同步,应该连接到 FPGA 内的的 AXI4 主机。
|
||||
|
||||
```Verilog
|
||||
input wire awvalid,
|
||||
@ -214,7 +214,7 @@ AXI4 总线的地址(awaddr和araddr)统一是字节地址,模块会根据
|
||||
### AXI4 写操作时序
|
||||
|
||||
__ __ __ __ __ __ __ __ __ __ __ __ _
|
||||
aclk __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/
|
||||
clk __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/
|
||||
___________
|
||||
awvalid ___/ \____________________________________________________________
|
||||
_____
|
||||
@ -245,7 +245,7 @@ AXI4 总线的地址(awaddr和araddr)统一是字节地址,模块会根据
|
||||
### AXI4 读操作时序
|
||||
|
||||
__ __ __ __ __ __ __ __ __ __ __ __ _
|
||||
aclk __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/
|
||||
clk __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/
|
||||
___________
|
||||
arvalid ___/ \____________________________________________________________
|
||||
_____
|
||||
@ -295,9 +295,9 @@ AXI4 总线的地址(awaddr和araddr)统一是字节地址,模块会根据
|
||||
|
||||
本节讲述如何确定 **tREFC**、**tW2I** 和 **tR2I** 这 3 个时序参数。
|
||||
|
||||
我们知道,DDR1 需要周期性的刷新动作,**tREFC** 就规定了刷新的时钟周期间隔(以 aclk为准)。例如,若用户时钟为 75MHz,根据 MT46V64M8 的芯片手册,需要至多 7.8125us 刷新一次,考虑到 75MHz * 7.8125us = 585.9,则该参数可以设置为一个小于 585 的值,例如 10'd512。
|
||||
我们知道,DDR1 需要周期性的刷新动作,**tREFC** 就规定了刷新的时钟周期间隔(以 clk 为准)。例如,若用户时钟为 75MHz,根据 MT46V64M8 的芯片手册,需要至多 7.8125us 刷新一次,考虑到 75MHz * 7.8125us = 585.9,则该参数可以设置为一个小于 585 的值,例如 10'd512。
|
||||
|
||||
**tW2I** 规定了一个写操作的最后一个写命令到下一个操作的激活命令(ACT)的时钟周期数(以 aclk 为准)的最小值。下图展示了一个 DDR1 接口上的写操作,ddr_cas_n 的第一个上升沿代表了一个写操作的最后一个写命令结束,ddr_ras_n 的第二个下降沿代表了下一个操作(可能是读、写、刷新)的开始,它们之间有 5 个时钟周期,**tW2I** 就是用来规定该周期数的下限的。**tW2I** 的默认值 8'd7 是一个兼容绝大多数 DDR1 的保守值,对于不同的 DDR1 芯片,有不同的缩小的余地(详见 DDR1 芯片 datasheet)。
|
||||
**tW2I** 规定了一个写操作的最后一个写命令到下一个操作的激活命令(ACT)的时钟周期数(以 clk 为准)的最小值。下图展示了一个 DDR1 接口上的写操作,ddr_cas_n 的第一个上升沿代表了一个写操作的最后一个写命令结束,ddr_ras_n 的第二个下降沿代表了下一个操作(可能是读、写、刷新)的开始,它们之间有 5 个时钟周期,**tW2I** 就是用来规定该周期数的下限的。**tW2I** 的默认值 8'd7 是一个兼容绝大多数 DDR1 的保守值,对于不同的 DDR1 芯片,有不同的缩小的余地(详见 DDR1 芯片 datasheet)。
|
||||
|
||||
__ __ __ __ __ __ __ __ __ __ __ __
|
||||
ddr_ck_p __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__
|
||||
@ -314,7 +314,7 @@ AXI4 总线的地址(awaddr和araddr)统一是字节地址,模块会根据
|
||||
_______________________
|
||||
ddr_a XXXXXX__RA_XXXXXXX_CA0_X_CA1_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
**tR2I** 规定了一个读操作的最后一个读命令到下一个操作的激活命令(ACT)的时钟周期数(以 aclk 为准)的最小值。下图展示了一个 DDR1 接口上的读操作,ddr_cas_n 的第一个上升沿代表了一个读操作的最后一个读命令结束,ddr_ras_n 的第二个下降沿代表了下一个操作(可能是读、写、刷新)的开始,它们之间有 5 个时钟周期,**tR2I** 就是用来规定该周期数的下限的。**tR2I** 的默认值 8'd7 是一个兼容绝大多数 DDR1 的保守值,对于不同的 DDR1 芯片,有不同的缩小的余地(详见 DDR1 芯片 datasheet)。
|
||||
**tR2I** 规定了一个读操作的最后一个读命令到下一个操作的激活命令(ACT)的时钟周期数(以 clk 为准)的最小值。下图展示了一个 DDR1 接口上的读操作,ddr_cas_n 的第一个上升沿代表了一个读操作的最后一个读命令结束,ddr_ras_n 的第二个下降沿代表了下一个操作(可能是读、写、刷新)的开始,它们之间有 5 个时钟周期,**tR2I** 就是用来规定该周期数的下限的。**tR2I** 的默认值 8'd7 是一个兼容绝大多数 DDR1 的保守值,对于不同的 DDR1 芯片,有不同的缩小的余地(详见 DDR1 芯片 datasheet)。
|
||||
|
||||
__ __ __ __ __ __ __ __ __ __ __ __
|
||||
ddr_ck_p __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__
|
||||
@ -345,8 +345,7 @@ AXI4 总线的地址(awaddr和araddr)统一是字节地址,模块会根据
|
||||
| :---- | :--- |
|
||||
| example-selftest/RTL/top.sv | 顶层 |
|
||||
| example-selftest/RTL/axi_self_test_master.sv | 是 AXI4 主机,通过 AXI4 先把有规律的数据写入 DDR1,然后读回,比较读回的数据是否符合规律,并对不匹配的情况进行计数。 |
|
||||
| example-selftest/RTL/pll.v | 使用板上 50MHz 晶振产生 300MHz 时钟,输出给 DDR1 控制器 |
|
||||
| /RTL/ddr_sdram_ctrl.sv | DDR1 控制器 |
|
||||
| RTL/ddr_sdram_ctrl.sv | DDR1 控制器 |
|
||||
|
||||
该示例程序的行为是:
|
||||
|
||||
@ -370,7 +369,6 @@ AXI4 总线的地址(awaddr和araddr)统一是字节地址,模块会根据
|
||||
| :---- | :--- |
|
||||
| example-uart-read-write/RTL/top.sv | 顶层 |
|
||||
| example-uart-read-write/RTL/uart2axi4.sv | 是 AXI4 主机,能把 UART RX 收到的命令转换成 AXI4 读写操作,并把读操作读出的数据通过 UART TX 发送出去 |
|
||||
| example-uart-read-write/RTL/pll.v | 使用板上 50MHz 晶振产生 300MHz 时钟,输出给 DDR1 控制器 |
|
||||
| RTL/ddr_sdram_ctrl.sv | DDR1 控制器 |
|
||||
|
||||
[FPGA+DDR1测试板](#硬件设计示例)上有一个 CH340E 芯片(USB 转 UART),因此插上 USB 线后就可以在电脑上看见 UART 对应的 COM 口(需要先在 [www.wch.cn/product/CH340.html](http://www.wch.cn/product/CH340.html) 下载安装 CH341 的驱动)。
|
||||
|
@ -22,10 +22,11 @@ module ddr_sdram_ctrl #(
|
||||
) (
|
||||
// driving clock and reset
|
||||
input wire rstn_async,
|
||||
input wire clk, // driving clock, typically 300~532MHz
|
||||
// user interface ( AXI4 )
|
||||
output reg aresetn,
|
||||
output reg aclk, // freq = F(clk)/4
|
||||
input wire drv_clk, // driving clock, typically 300~532MHz
|
||||
// generate clock for AXI4
|
||||
output reg rstn,
|
||||
output reg clk, // freq = F(drv_clk)/4
|
||||
// user interface (AXI4)
|
||||
input wire awvalid,
|
||||
output wire awready,
|
||||
input wire [BA_BITS+ROW_BITS+COL_BITS+DQ_LEVEL-2:0] awaddr, // byte address, not word address.
|
||||
@ -45,7 +46,7 @@ module ddr_sdram_ctrl #(
|
||||
output wire rlast,
|
||||
output wire [(8<<DQ_LEVEL)-1:0] rdata,
|
||||
// DDR-SDRAM interface
|
||||
output wire ddr_ck_p, ddr_ck_n, // freq = F(clk)/4
|
||||
output wire ddr_ck_p, ddr_ck_n, // freq = F(drv_clk)/4
|
||||
output wire ddr_cke,
|
||||
output reg ddr_cs_n,
|
||||
output reg ddr_ras_n,
|
||||
@ -120,26 +121,26 @@ initial ddr_we_n = 1'b1;
|
||||
initial ddr_ba = '0;
|
||||
initial ddr_a = DDR_A_DEFAULT;
|
||||
|
||||
initial {aresetn, aclk} = '0;
|
||||
initial {rstn, clk} = '0;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// generate reset sync with clk
|
||||
// generate reset sync with drv_clk
|
||||
// -------------------------------------------------------------------------------------
|
||||
reg rstn_clk = '0;
|
||||
reg [1:0] rstn_clk_l = '0;
|
||||
always @ (posedge clk or negedge rstn_async)
|
||||
reg [2:0] rstn_clk_l = '0;
|
||||
always @ (posedge drv_clk or negedge rstn_async)
|
||||
if(~rstn_async)
|
||||
{rstn_clk, rstn_clk_l} <= '0;
|
||||
else
|
||||
{rstn_clk, rstn_clk_l} <= {rstn_clk_l, 1'b1};
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// generate reset sync with aclk
|
||||
// generate reset sync with clk
|
||||
// -------------------------------------------------------------------------------------
|
||||
reg rstn_aclk = '0;
|
||||
reg [1:0] rstn_aclk_l = '0;
|
||||
always @ (posedge aclk or negedge rstn_async)
|
||||
reg [2:0] rstn_aclk_l = '0;
|
||||
always @ (posedge clk or negedge rstn_async)
|
||||
if(~rstn_async)
|
||||
{rstn_aclk, rstn_aclk_l} <= '0;
|
||||
else
|
||||
@ -148,25 +149,25 @@ always @ (posedge aclk or negedge rstn_async)
|
||||
// -------------------------------------------------------------------------------------
|
||||
// generate clocks
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge clk or negedge rstn_clk)
|
||||
always @ (posedge drv_clk or negedge rstn_clk)
|
||||
if(~rstn_clk)
|
||||
{aclk,clk2} <= 2'b00;
|
||||
{clk,clk2} <= 2'b00;
|
||||
else
|
||||
{aclk,clk2} <= {aclk,clk2} + 2'b01;
|
||||
{clk,clk2} <= {clk,clk2} + 2'b01;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// generate user reset
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge aclk or negedge rstn_aclk)
|
||||
always @ (posedge clk or negedge rstn_aclk)
|
||||
if(~rstn_aclk)
|
||||
aresetn <= 1'b0;
|
||||
rstn <= 1'b0;
|
||||
else
|
||||
aresetn <= init_done;
|
||||
rstn <= init_done;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// refresh wptr self increasement
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge aclk or negedge rstn_aclk)
|
||||
always @ (posedge clk or negedge rstn_aclk)
|
||||
if(~rstn_aclk) begin
|
||||
ref_cnt <= '0;
|
||||
ref_idle <= 3'd1;
|
||||
@ -184,8 +185,8 @@ always @ (posedge aclk or negedge rstn_aclk)
|
||||
// -------------------------------------------------------------------------------------
|
||||
// generate DDR clock
|
||||
// -------------------------------------------------------------------------------------
|
||||
assign ddr_ck_p = ~aclk;
|
||||
assign ddr_ck_n = aclk;
|
||||
assign ddr_ck_p = ~clk;
|
||||
assign ddr_ck_n = clk;
|
||||
assign ddr_cke = ~ddr_cs_n;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
@ -196,7 +197,7 @@ assign ddr_dqs = output_enable ? {DQS_BITS{o_dqs_c}} : 'z;
|
||||
assign ddr_dq = output_enable ? o_d_d : 'z;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// assignment for user interface (meta AXI4 interface)
|
||||
// assignment for user interface (AXI4)
|
||||
// -------------------------------------------------------------------------------------
|
||||
assign awready = stat==IDLE && init_done && ref_real==ref_idle;
|
||||
assign wready = stat==WRITE;
|
||||
@ -206,7 +207,7 @@ assign arready = stat==IDLE && init_done && ref_real==ref_idle && ~awvalid && re
|
||||
// -------------------------------------------------------------------------------------
|
||||
// main FSM for generating DDR-SDRAM behavior
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge aclk or negedge rstn_aclk)
|
||||
always @ (posedge clk or negedge rstn_aclk)
|
||||
if(~rstn_aclk) begin
|
||||
ddr_cs_n <= 1'b1;
|
||||
ddr_ras_n <= 1'b1;
|
||||
@ -372,8 +373,8 @@ always @ (posedge aclk or negedge rstn_aclk)
|
||||
// -------------------------------------------------------------------------------------
|
||||
// output enable generate
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
output_enable <= 1'b0;
|
||||
output_enable_d1 <= 1'b0;
|
||||
output_enable_d2 <= 1'b0;
|
||||
@ -386,8 +387,8 @@ always @ (posedge aclk or negedge aresetn)
|
||||
// -------------------------------------------------------------------------------------
|
||||
// output data latches --- stage A
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
o_v_a <= 1'b0;
|
||||
{o_dh_a, o_dl_a} <= '0;
|
||||
end else begin
|
||||
@ -398,8 +399,8 @@ always @ (posedge aclk or negedge aresetn)
|
||||
// -------------------------------------------------------------------------------------
|
||||
// output data latches --- stage B
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
o_v_b <= 1'b0;
|
||||
o_dh_b <= '0;
|
||||
end else begin
|
||||
@ -411,7 +412,7 @@ always @ (posedge aclk or negedge aresetn)
|
||||
// dq and dqs generate for output (write)
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge clk2)
|
||||
if(~aclk) begin
|
||||
if(~clk) begin
|
||||
o_dqs_c <= 1'b0;
|
||||
o_d_c <= o_v_a ? o_dl_a : '0;
|
||||
end else begin
|
||||
@ -422,7 +423,7 @@ always @ (posedge clk2)
|
||||
// -------------------------------------------------------------------------------------
|
||||
// dq delay for output (write)
|
||||
// -------------------------------------------------------------------------------------
|
||||
always @ (posedge clk)
|
||||
always @ (posedge drv_clk)
|
||||
o_d_d <= o_d_c;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
@ -437,8 +438,8 @@ always @ (posedge clk2)
|
||||
if(i_dqs_c)
|
||||
i_d_d <= {ddr_dq, i_d_c};
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
{i_v_a, i_v_b, i_v_c, i_v_d} <= '0;
|
||||
{i_l_a, i_l_b, i_l_c, i_l_d} <= '0;
|
||||
end else begin
|
||||
@ -452,8 +453,8 @@ always @ (posedge aclk or negedge aresetn)
|
||||
i_l_d <= i_l_c;
|
||||
end
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
i_v_e <= 1'b0;
|
||||
i_l_e <= 1'b0;
|
||||
i_d_e <= '0;
|
||||
@ -485,20 +486,20 @@ generate if(READ_BUFFER) begin
|
||||
assign rreq = emptyn & ( rready | ~rvalid );
|
||||
assign {rlast, rdata} = dvalid ? fifo_rdata : datareg;
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn)
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn)
|
||||
wpt <= 0;
|
||||
else if(i_v_e & itready)
|
||||
wpt <= wpt + (AWIDTH)'(1);
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn)
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn)
|
||||
rpt <= 0;
|
||||
else if(rreq & emptyn)
|
||||
rpt <= rpt + (AWIDTH)'(1);
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
dvalid <= 1'b0;
|
||||
valid <= 1'b0;
|
||||
datareg <= 0;
|
||||
@ -514,11 +515,11 @@ generate if(READ_BUFFER) begin
|
||||
|
||||
reg [DWIDTH-1:0] mem [(1<<AWIDTH)];
|
||||
|
||||
always @ (posedge aclk)
|
||||
always @ (posedge clk)
|
||||
if(i_v_e)
|
||||
mem[wpt] <= {i_l_e, i_d_e};
|
||||
|
||||
always @ (posedge aclk)
|
||||
always @ (posedge clk)
|
||||
fifo_rdata <= mem[rpt];
|
||||
|
||||
assign read_accessible = ~rvalid;
|
||||
|
@ -15,8 +15,8 @@ module axi_self_test_master #(
|
||||
parameter [7:0] WBURST_LEN = 8'd7,
|
||||
parameter [7:0] RBURST_LEN = 8'd7
|
||||
)(
|
||||
input wire aresetn,
|
||||
input wire aclk,
|
||||
input wire rstn,
|
||||
input wire clk,
|
||||
output wire awvalid,
|
||||
input wire awready,
|
||||
output reg [A_WIDTH-1:0] awaddr,
|
||||
@ -65,8 +65,8 @@ assign rready = 1'b1;
|
||||
|
||||
wire [A_WIDTH:0] araddr_next = {1'b0,araddr} + (A_WIDTH+1)'(1<<D_LEVEL);
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
{awaddr_carry, awaddr} <= '0;
|
||||
w_cnt <= 8'd0;
|
||||
araddr <= '0;
|
||||
@ -110,8 +110,8 @@ always @ (posedge aclk or negedge aresetn)
|
||||
// read and write mismatch detect
|
||||
// ------------------------------------------------------------
|
||||
wire [D_WIDTH-1:0] rdata_idle = (D_WIDTH)'(araddr);
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
error <= 1'b0;
|
||||
error_cnt <= 16'd0;
|
||||
end else begin
|
||||
|
@ -40,13 +40,13 @@ localparam DQ_BITS = (4<<DQ_LEVEL);
|
||||
localparam DQS_BITS = ((1<<DQ_LEVEL)+1)/2;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 burst length parameters
|
||||
// AXI4 burst length parameters
|
||||
// -------------------------------------------------------------------------------------
|
||||
localparam [7:0] WBURST_LEN = 8'd7;
|
||||
localparam [7:0] RBURST_LEN = 8'd7;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 parameters
|
||||
// AXI4 parameters
|
||||
// -------------------------------------------------------------------------------------
|
||||
localparam A_WIDTH = BA_BITS+ROW_BITS+COL_BITS+DQ_LEVEL-1;
|
||||
localparam D_WIDTH = (8<<DQ_LEVEL);
|
||||
@ -54,9 +54,9 @@ localparam D_WIDTH = (8<<DQ_LEVEL);
|
||||
// -------------------------------------------------------------------------------------
|
||||
// driving clock and reset generate
|
||||
// -------------------------------------------------------------------------------------
|
||||
reg rstn=1'b0, clk300m=1'b1;
|
||||
reg rstn_async=1'b0, clk300m=1'b1;
|
||||
always #1667 clk300m = ~clk300m;
|
||||
initial begin repeat(4) @(posedge clk300m); rstn<=1'b1; end
|
||||
initial begin repeat(4) @(posedge clk300m); rstn_async<=1'b1; end
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// DDR-SDRAM signal
|
||||
@ -71,10 +71,10 @@ tri [DQS_BITS-1:0] ddr_dqs;
|
||||
tri [ DQ_BITS-1:0] ddr_dq;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 interface
|
||||
// AXI4 interface
|
||||
// -------------------------------------------------------------------------------------
|
||||
wire aresetn;
|
||||
wire aclk;
|
||||
wire rstn;
|
||||
wire clk;
|
||||
wire awvalid;
|
||||
wire awready;
|
||||
wire [A_WIDTH-1:0] awaddr;
|
||||
@ -95,7 +95,7 @@ wire rlast;
|
||||
wire [D_WIDTH-1:0] rdata;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 master for testing
|
||||
// AXI4 master for testing
|
||||
// -------------------------------------------------------------------------------------
|
||||
axi_self_test_master #(
|
||||
.A_WIDTH_TEST( 12 ),
|
||||
@ -105,8 +105,8 @@ axi_self_test_master #(
|
||||
.WBURST_LEN ( WBURST_LEN ),
|
||||
.RBURST_LEN ( RBURST_LEN )
|
||||
) axi_m_i (
|
||||
.aresetn ( aresetn ),
|
||||
.aclk ( aclk ),
|
||||
.rstn ( rstn ),
|
||||
.clk ( clk ),
|
||||
.awvalid ( awvalid ),
|
||||
.awready ( awready ),
|
||||
.awaddr ( awaddr ),
|
||||
@ -142,10 +142,10 @@ ddr_sdram_ctrl #(
|
||||
.tW2I ( 8'd6 ),
|
||||
.tR2I ( 8'd6 )
|
||||
) ddr_sdram_ctrl_i (
|
||||
.rstn_async ( rstn ),
|
||||
.clk ( clk300m ),
|
||||
.aresetn ( aresetn ),
|
||||
.aclk ( aclk ),
|
||||
.rstn_async ( rstn_async ),
|
||||
.drv_clk ( clk300m ),
|
||||
.rstn ( rstn ),
|
||||
.clk ( clk ),
|
||||
.awvalid ( awvalid ),
|
||||
.awready ( awready ),
|
||||
.awaddr ( awaddr ),
|
||||
|
@ -15,8 +15,8 @@ module axi_self_test_master #(
|
||||
parameter [7:0] WBURST_LEN = 8'd7,
|
||||
parameter [7:0] RBURST_LEN = 8'd7
|
||||
)(
|
||||
input wire aresetn,
|
||||
input wire aclk,
|
||||
input wire rstn,
|
||||
input wire clk,
|
||||
output wire awvalid,
|
||||
input wire awready,
|
||||
output reg [A_WIDTH-1:0] awaddr,
|
||||
@ -65,8 +65,8 @@ assign rready = 1'b1;
|
||||
|
||||
wire [A_WIDTH:0] araddr_next = {1'b0,araddr} + (A_WIDTH+1)'(1<<D_LEVEL);
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
{awaddr_carry, awaddr} <= '0;
|
||||
w_cnt <= 8'd0;
|
||||
araddr <= '0;
|
||||
@ -110,8 +110,8 @@ always @ (posedge aclk or negedge aresetn)
|
||||
// read and write mismatch detect
|
||||
// ------------------------------------------------------------
|
||||
wire [D_WIDTH-1:0] rdata_idle = (D_WIDTH)'(araddr);
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
error <= 1'b0;
|
||||
error_cnt <= 16'd0;
|
||||
end else begin
|
||||
|
@ -1,115 +0,0 @@
|
||||
`timescale 1 ns / 1 ns
|
||||
|
||||
// synopsys translate_on
|
||||
module pll (
|
||||
input wire inclk0,
|
||||
output wire c0,
|
||||
output wire locked
|
||||
);
|
||||
|
||||
wire [4:0] sub_wire0;
|
||||
wire sub_wire2;
|
||||
wire [0:0] sub_wire5 = 1'h0;
|
||||
wire [0:0] sub_wire1 = sub_wire0[0:0];
|
||||
assign c0 = sub_wire1;
|
||||
assign locked = sub_wire2;
|
||||
wire sub_wire3 = inclk0;
|
||||
wire [1:0] sub_wire4 = {sub_wire5, sub_wire3};
|
||||
|
||||
altpll altpll_component (
|
||||
.inclk (sub_wire4),
|
||||
.clk (sub_wire0),
|
||||
.locked (sub_wire2),
|
||||
.activeclock (),
|
||||
.areset (1'b0),
|
||||
.clkbad (),
|
||||
.clkena ({6{1'b1}}),
|
||||
.clkloss (),
|
||||
.clkswitch (1'b0),
|
||||
.configupdate (1'b0),
|
||||
.enable0 (),
|
||||
.enable1 (),
|
||||
.extclk (),
|
||||
.extclkena ({4{1'b1}}),
|
||||
.fbin (1'b1),
|
||||
.fbmimicbidir (),
|
||||
.fbout (),
|
||||
.fref (),
|
||||
.icdrclk (),
|
||||
.pfdena (1'b1),
|
||||
.phasecounterselect ({4{1'b1}}),
|
||||
.phasedone (),
|
||||
.phasestep (1'b1),
|
||||
.phaseupdown (1'b1),
|
||||
.pllena (1'b1),
|
||||
.scanaclr (1'b0),
|
||||
.scanclk (1'b0),
|
||||
.scanclkena (1'b1),
|
||||
.scandata (1'b0),
|
||||
.scandataout (),
|
||||
.scandone (),
|
||||
.scanread (1'b0),
|
||||
.scanwrite (1'b0),
|
||||
.sclkout0 (),
|
||||
.sclkout1 (),
|
||||
.vcooverrange (),
|
||||
.vcounderrange ());
|
||||
defparam
|
||||
altpll_component.bandwidth_type = "AUTO",
|
||||
altpll_component.clk0_divide_by = 1,
|
||||
altpll_component.clk0_duty_cycle = 50,
|
||||
altpll_component.clk0_multiply_by = 6,
|
||||
altpll_component.clk0_phase_shift = "0",
|
||||
altpll_component.compensate_clock = "CLK0",
|
||||
altpll_component.inclk0_input_frequency = 20000,
|
||||
altpll_component.intended_device_family = "Cyclone IV E",
|
||||
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
|
||||
altpll_component.lpm_type = "altpll",
|
||||
altpll_component.operation_mode = "NORMAL",
|
||||
altpll_component.pll_type = "AUTO",
|
||||
altpll_component.port_activeclock = "PORT_UNUSED",
|
||||
altpll_component.port_areset = "PORT_UNUSED",
|
||||
altpll_component.port_clkbad0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkbad1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkloss = "PORT_UNUSED",
|
||||
altpll_component.port_clkswitch = "PORT_UNUSED",
|
||||
altpll_component.port_configupdate = "PORT_UNUSED",
|
||||
altpll_component.port_fbin = "PORT_UNUSED",
|
||||
altpll_component.port_inclk0 = "PORT_USED",
|
||||
altpll_component.port_inclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_locked = "PORT_USED",
|
||||
altpll_component.port_pfdena = "PORT_UNUSED",
|
||||
altpll_component.port_phasecounterselect = "PORT_UNUSED",
|
||||
altpll_component.port_phasedone = "PORT_UNUSED",
|
||||
altpll_component.port_phasestep = "PORT_UNUSED",
|
||||
altpll_component.port_phaseupdown = "PORT_UNUSED",
|
||||
altpll_component.port_pllena = "PORT_UNUSED",
|
||||
altpll_component.port_scanaclr = "PORT_UNUSED",
|
||||
altpll_component.port_scanclk = "PORT_UNUSED",
|
||||
altpll_component.port_scanclkena = "PORT_UNUSED",
|
||||
altpll_component.port_scandata = "PORT_UNUSED",
|
||||
altpll_component.port_scandataout = "PORT_UNUSED",
|
||||
altpll_component.port_scandone = "PORT_UNUSED",
|
||||
altpll_component.port_scanread = "PORT_UNUSED",
|
||||
altpll_component.port_scanwrite = "PORT_UNUSED",
|
||||
altpll_component.port_clk0 = "PORT_USED",
|
||||
altpll_component.port_clk1 = "PORT_UNUSED",
|
||||
altpll_component.port_clk2 = "PORT_UNUSED",
|
||||
altpll_component.port_clk3 = "PORT_UNUSED",
|
||||
altpll_component.port_clk4 = "PORT_UNUSED",
|
||||
altpll_component.port_clk5 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena2 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena3 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena4 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena5 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk0 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk2 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk3 = "PORT_UNUSED",
|
||||
altpll_component.self_reset_on_loss_lock = "OFF",
|
||||
altpll_component.width_clock = 5;
|
||||
|
||||
|
||||
endmodule
|
@ -35,7 +35,7 @@ localparam DQ_BITS = (4<<DQ_LEVEL);
|
||||
localparam DQS_BITS = ((1<<DQ_LEVEL)+1)/2;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 parameters
|
||||
// AXI4 parameters
|
||||
// -------------------------------------------------------------------------------------
|
||||
localparam A_WIDTH = BA_BITS+ROW_BITS+COL_BITS+DQ_LEVEL-1;
|
||||
localparam D_WIDTH = (8<<DQ_LEVEL);
|
||||
@ -44,13 +44,13 @@ localparam D_WIDTH = (8<<DQ_LEVEL);
|
||||
// driving clock and reset
|
||||
// -------------------------------------------------------------------------------------
|
||||
wire clk300m;
|
||||
wire rstn;
|
||||
wire locked;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 interface
|
||||
// AXI4 interface
|
||||
// -------------------------------------------------------------------------------------
|
||||
wire aresetn;
|
||||
wire aclk;
|
||||
wire rstn;
|
||||
wire clk;
|
||||
wire awvalid;
|
||||
wire awready;
|
||||
wire [A_WIDTH-1:0] awaddr;
|
||||
@ -70,17 +70,17 @@ wire rready;
|
||||
wire rlast;
|
||||
wire [D_WIDTH-1:0] rdata;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// PLL for generating 300MHz clock
|
||||
// -------------------------------------------------------------------------------------
|
||||
pll pll_i(
|
||||
.inclk0 ( clk50m ),
|
||||
.c0 ( clk300m ),
|
||||
.locked ( rstn )
|
||||
);
|
||||
wire [3:0] subwire0;
|
||||
altpll altpll_i( .inclk ( {1'b0, clk50m} ), .clk ( {subwire0, clk300m} ), .locked ( locked ), .activeclock (), .areset (1'b0), .clkbad (), .clkena ({6{1'b1}}), .clkloss (), .clkswitch (1'b0), .configupdate (1'b0), .enable0 (), .enable1 (), .extclk (), .extclkena ({4{1'b1}}), .fbin (1'b1), .fbmimicbidir (), .fbout (), .fref (), .icdrclk (), .pfdena (1'b1), .phasecounterselect ({4{1'b1}}), .phasedone (), .phasestep (1'b1), .phaseupdown (1'b1), .pllena (1'b1), .scanaclr (1'b0), .scanclk (1'b0), .scanclkena (1'b1), .scandata (1'b0), .scandataout (), .scandone (), .scanread (1'b0), .scanwrite (1'b0), .sclkout0 (), .sclkout1 (), .vcooverrange (), .vcounderrange ());
|
||||
defparam altpll_i.bandwidth_type = "AUTO", altpll_i.clk0_divide_by = 1, altpll_i.clk0_duty_cycle = 50, altpll_i.clk0_multiply_by = 6, altpll_i.clk0_phase_shift = "0", altpll_i.compensate_clock = "CLK0", altpll_i.inclk0_input_frequency = 20000, altpll_i.intended_device_family = "Cyclone IV E", altpll_i.lpm_hint = "CBX_MODULE_PREFIX=pll", altpll_i.lpm_type = "altpll", altpll_i.operation_mode = "NORMAL", altpll_i.pll_type = "AUTO", altpll_i.port_activeclock = "PORT_UNUSED", altpll_i.port_areset = "PORT_UNUSED", altpll_i.port_clkbad0 = "PORT_UNUSED", altpll_i.port_clkbad1 = "PORT_UNUSED", altpll_i.port_clkloss = "PORT_UNUSED", altpll_i.port_clkswitch = "PORT_UNUSED", altpll_i.port_configupdate = "PORT_UNUSED", altpll_i.port_fbin = "PORT_UNUSED", altpll_i.port_inclk0 = "PORT_USED", altpll_i.port_inclk1 = "PORT_UNUSED", altpll_i.port_locked = "PORT_USED", altpll_i.port_pfdena = "PORT_UNUSED", altpll_i.port_phasecounterselect = "PORT_UNUSED", altpll_i.port_phasedone = "PORT_UNUSED", altpll_i.port_phasestep = "PORT_UNUSED", altpll_i.port_phaseupdown = "PORT_UNUSED", altpll_i.port_pllena = "PORT_UNUSED", altpll_i.port_scanaclr = "PORT_UNUSED", altpll_i.port_scanclk = "PORT_UNUSED", altpll_i.port_scanclkena = "PORT_UNUSED", altpll_i.port_scandata = "PORT_UNUSED", altpll_i.port_scandataout = "PORT_UNUSED", altpll_i.port_scandone = "PORT_UNUSED", altpll_i.port_scanread = "PORT_UNUSED", altpll_i.port_scanwrite = "PORT_UNUSED", altpll_i.port_clk0 = "PORT_USED", altpll_i.port_clk1 = "PORT_UNUSED", altpll_i.port_clk2 = "PORT_UNUSED", altpll_i.port_clk3 = "PORT_UNUSED", altpll_i.port_clk4 = "PORT_UNUSED", altpll_i.port_clk5 = "PORT_UNUSED", altpll_i.port_clkena0 = "PORT_UNUSED", altpll_i.port_clkena1 = "PORT_UNUSED", altpll_i.port_clkena2 = "PORT_UNUSED", altpll_i.port_clkena3 = "PORT_UNUSED", altpll_i.port_clkena4 = "PORT_UNUSED", altpll_i.port_clkena5 = "PORT_UNUSED", altpll_i.port_extclk0 = "PORT_UNUSED", altpll_i.port_extclk1 = "PORT_UNUSED", altpll_i.port_extclk2 = "PORT_UNUSED", altpll_i.port_extclk3 = "PORT_UNUSED", altpll_i.self_reset_on_loss_lock = "OFF", altpll_i.width_clock = 5;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 master for testing
|
||||
// AXI4 master for testing
|
||||
// -------------------------------------------------------------------------------------
|
||||
axi_self_test_master #(
|
||||
.A_WIDTH_TEST( A_WIDTH ),
|
||||
@ -90,8 +90,8 @@ axi_self_test_master #(
|
||||
.WBURST_LEN ( 8'd15 ),
|
||||
.RBURST_LEN ( 8'd15 )
|
||||
) axi_m_i (
|
||||
.aresetn ( aresetn ),
|
||||
.aclk ( aclk ),
|
||||
.rstn ( rstn ),
|
||||
.clk ( clk ),
|
||||
.awvalid ( awvalid ),
|
||||
.awready ( awready ),
|
||||
.awaddr ( awaddr ),
|
||||
@ -114,6 +114,7 @@ axi_self_test_master #(
|
||||
.error_cnt ( error_cnt )
|
||||
);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// DDR-SDRAM controller
|
||||
// -------------------------------------------------------------------------------------
|
||||
@ -127,10 +128,10 @@ ddr_sdram_ctrl #(
|
||||
.tW2I ( 8'd7 ),
|
||||
.tR2I ( 8'd7 )
|
||||
) ddr_ctrl_i(
|
||||
.rstn_async ( rstn ),
|
||||
.clk ( clk300m ),
|
||||
.aresetn ( aresetn ),
|
||||
.aclk ( aclk ),
|
||||
.rstn_async ( locked ),
|
||||
.drv_clk ( clk300m ),
|
||||
.rstn ( rstn ),
|
||||
.clk ( clk ),
|
||||
.awvalid ( awvalid ),
|
||||
.awready ( awready ),
|
||||
.awaddr ( awaddr ),
|
||||
|
@ -132,7 +132,6 @@ set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_clk -to "ddr_c
|
||||
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE RTL/top.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE RTL/axi_self_test_master.sv
|
||||
set_global_assignment -name VERILOG_FILE RTL/pll.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ../RTL/ddr_sdram_ctrl.sv
|
||||
set_global_assignment -name SIGNALTAP_FILE SignalTap/stp1.stp
|
||||
|
||||
|
@ -1,115 +0,0 @@
|
||||
`timescale 1 ns / 1 ns
|
||||
|
||||
// synopsys translate_on
|
||||
module pll (
|
||||
input wire inclk0,
|
||||
output wire c0,
|
||||
output wire locked
|
||||
);
|
||||
|
||||
wire [4:0] sub_wire0;
|
||||
wire sub_wire2;
|
||||
wire [0:0] sub_wire5 = 1'h0;
|
||||
wire [0:0] sub_wire1 = sub_wire0[0:0];
|
||||
assign c0 = sub_wire1;
|
||||
assign locked = sub_wire2;
|
||||
wire sub_wire3 = inclk0;
|
||||
wire [1:0] sub_wire4 = {sub_wire5, sub_wire3};
|
||||
|
||||
altpll altpll_component (
|
||||
.inclk (sub_wire4),
|
||||
.clk (sub_wire0),
|
||||
.locked (sub_wire2),
|
||||
.activeclock (),
|
||||
.areset (1'b0),
|
||||
.clkbad (),
|
||||
.clkena ({6{1'b1}}),
|
||||
.clkloss (),
|
||||
.clkswitch (1'b0),
|
||||
.configupdate (1'b0),
|
||||
.enable0 (),
|
||||
.enable1 (),
|
||||
.extclk (),
|
||||
.extclkena ({4{1'b1}}),
|
||||
.fbin (1'b1),
|
||||
.fbmimicbidir (),
|
||||
.fbout (),
|
||||
.fref (),
|
||||
.icdrclk (),
|
||||
.pfdena (1'b1),
|
||||
.phasecounterselect ({4{1'b1}}),
|
||||
.phasedone (),
|
||||
.phasestep (1'b1),
|
||||
.phaseupdown (1'b1),
|
||||
.pllena (1'b1),
|
||||
.scanaclr (1'b0),
|
||||
.scanclk (1'b0),
|
||||
.scanclkena (1'b1),
|
||||
.scandata (1'b0),
|
||||
.scandataout (),
|
||||
.scandone (),
|
||||
.scanread (1'b0),
|
||||
.scanwrite (1'b0),
|
||||
.sclkout0 (),
|
||||
.sclkout1 (),
|
||||
.vcooverrange (),
|
||||
.vcounderrange ());
|
||||
defparam
|
||||
altpll_component.bandwidth_type = "AUTO",
|
||||
altpll_component.clk0_divide_by = 1,
|
||||
altpll_component.clk0_duty_cycle = 50,
|
||||
altpll_component.clk0_multiply_by = 6,
|
||||
altpll_component.clk0_phase_shift = "0",
|
||||
altpll_component.compensate_clock = "CLK0",
|
||||
altpll_component.inclk0_input_frequency = 20000,
|
||||
altpll_component.intended_device_family = "Cyclone IV E",
|
||||
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
|
||||
altpll_component.lpm_type = "altpll",
|
||||
altpll_component.operation_mode = "NORMAL",
|
||||
altpll_component.pll_type = "AUTO",
|
||||
altpll_component.port_activeclock = "PORT_UNUSED",
|
||||
altpll_component.port_areset = "PORT_UNUSED",
|
||||
altpll_component.port_clkbad0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkbad1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkloss = "PORT_UNUSED",
|
||||
altpll_component.port_clkswitch = "PORT_UNUSED",
|
||||
altpll_component.port_configupdate = "PORT_UNUSED",
|
||||
altpll_component.port_fbin = "PORT_UNUSED",
|
||||
altpll_component.port_inclk0 = "PORT_USED",
|
||||
altpll_component.port_inclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_locked = "PORT_USED",
|
||||
altpll_component.port_pfdena = "PORT_UNUSED",
|
||||
altpll_component.port_phasecounterselect = "PORT_UNUSED",
|
||||
altpll_component.port_phasedone = "PORT_UNUSED",
|
||||
altpll_component.port_phasestep = "PORT_UNUSED",
|
||||
altpll_component.port_phaseupdown = "PORT_UNUSED",
|
||||
altpll_component.port_pllena = "PORT_UNUSED",
|
||||
altpll_component.port_scanaclr = "PORT_UNUSED",
|
||||
altpll_component.port_scanclk = "PORT_UNUSED",
|
||||
altpll_component.port_scanclkena = "PORT_UNUSED",
|
||||
altpll_component.port_scandata = "PORT_UNUSED",
|
||||
altpll_component.port_scandataout = "PORT_UNUSED",
|
||||
altpll_component.port_scandone = "PORT_UNUSED",
|
||||
altpll_component.port_scanread = "PORT_UNUSED",
|
||||
altpll_component.port_scanwrite = "PORT_UNUSED",
|
||||
altpll_component.port_clk0 = "PORT_USED",
|
||||
altpll_component.port_clk1 = "PORT_UNUSED",
|
||||
altpll_component.port_clk2 = "PORT_UNUSED",
|
||||
altpll_component.port_clk3 = "PORT_UNUSED",
|
||||
altpll_component.port_clk4 = "PORT_UNUSED",
|
||||
altpll_component.port_clk5 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena2 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena3 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena4 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena5 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk0 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk2 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk3 = "PORT_UNUSED",
|
||||
altpll_component.self_reset_on_loss_lock = "OFF",
|
||||
altpll_component.width_clock = 5;
|
||||
|
||||
|
||||
endmodule
|
@ -34,7 +34,7 @@ localparam DQ_BITS = (4<<DQ_LEVEL);
|
||||
localparam DQS_BITS = ((1<<DQ_LEVEL)+1)/2;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 parameters
|
||||
// AXI4 parameters
|
||||
// -------------------------------------------------------------------------------------
|
||||
localparam A_WIDTH = BA_BITS+ROW_BITS+COL_BITS+DQ_LEVEL-1;
|
||||
localparam D_WIDTH = (8<<DQ_LEVEL);
|
||||
@ -43,13 +43,13 @@ localparam D_WIDTH = (8<<DQ_LEVEL);
|
||||
// driving clock and reset
|
||||
// -------------------------------------------------------------------------------------
|
||||
wire clk300m;
|
||||
wire rstn;
|
||||
wire locked;
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 interface
|
||||
// AXI4 interface
|
||||
// -------------------------------------------------------------------------------------
|
||||
wire aresetn;
|
||||
wire aclk;
|
||||
wire rstn;
|
||||
wire clk;
|
||||
wire awvalid;
|
||||
wire awready;
|
||||
wire [A_WIDTH-1:0] awaddr;
|
||||
@ -69,23 +69,23 @@ wire rready;
|
||||
wire rlast;
|
||||
wire [D_WIDTH-1:0] rdata;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// PLL for generating 300MHz clock
|
||||
// -------------------------------------------------------------------------------------
|
||||
pll pll_i(
|
||||
.inclk0 ( clk50m ),
|
||||
.c0 ( clk300m ),
|
||||
.locked ( rstn )
|
||||
);
|
||||
wire [3:0] subwire0;
|
||||
altpll altpll_i( .inclk ( {1'b0, clk50m} ), .clk ( {subwire0, clk300m} ), .locked ( locked ), .activeclock (), .areset (1'b0), .clkbad (), .clkena ({6{1'b1}}), .clkloss (), .clkswitch (1'b0), .configupdate (1'b0), .enable0 (), .enable1 (), .extclk (), .extclkena ({4{1'b1}}), .fbin (1'b1), .fbmimicbidir (), .fbout (), .fref (), .icdrclk (), .pfdena (1'b1), .phasecounterselect ({4{1'b1}}), .phasedone (), .phasestep (1'b1), .phaseupdown (1'b1), .pllena (1'b1), .scanaclr (1'b0), .scanclk (1'b0), .scanclkena (1'b1), .scandata (1'b0), .scandataout (), .scandone (), .scanread (1'b0), .scanwrite (1'b0), .sclkout0 (), .sclkout1 (), .vcooverrange (), .vcounderrange ());
|
||||
defparam altpll_i.bandwidth_type = "AUTO", altpll_i.clk0_divide_by = 1, altpll_i.clk0_duty_cycle = 50, altpll_i.clk0_multiply_by = 6, altpll_i.clk0_phase_shift = "0", altpll_i.compensate_clock = "CLK0", altpll_i.inclk0_input_frequency = 20000, altpll_i.intended_device_family = "Cyclone IV E", altpll_i.lpm_hint = "CBX_MODULE_PREFIX=pll", altpll_i.lpm_type = "altpll", altpll_i.operation_mode = "NORMAL", altpll_i.pll_type = "AUTO", altpll_i.port_activeclock = "PORT_UNUSED", altpll_i.port_areset = "PORT_UNUSED", altpll_i.port_clkbad0 = "PORT_UNUSED", altpll_i.port_clkbad1 = "PORT_UNUSED", altpll_i.port_clkloss = "PORT_UNUSED", altpll_i.port_clkswitch = "PORT_UNUSED", altpll_i.port_configupdate = "PORT_UNUSED", altpll_i.port_fbin = "PORT_UNUSED", altpll_i.port_inclk0 = "PORT_USED", altpll_i.port_inclk1 = "PORT_UNUSED", altpll_i.port_locked = "PORT_USED", altpll_i.port_pfdena = "PORT_UNUSED", altpll_i.port_phasecounterselect = "PORT_UNUSED", altpll_i.port_phasedone = "PORT_UNUSED", altpll_i.port_phasestep = "PORT_UNUSED", altpll_i.port_phaseupdown = "PORT_UNUSED", altpll_i.port_pllena = "PORT_UNUSED", altpll_i.port_scanaclr = "PORT_UNUSED", altpll_i.port_scanclk = "PORT_UNUSED", altpll_i.port_scanclkena = "PORT_UNUSED", altpll_i.port_scandata = "PORT_UNUSED", altpll_i.port_scandataout = "PORT_UNUSED", altpll_i.port_scandone = "PORT_UNUSED", altpll_i.port_scanread = "PORT_UNUSED", altpll_i.port_scanwrite = "PORT_UNUSED", altpll_i.port_clk0 = "PORT_USED", altpll_i.port_clk1 = "PORT_UNUSED", altpll_i.port_clk2 = "PORT_UNUSED", altpll_i.port_clk3 = "PORT_UNUSED", altpll_i.port_clk4 = "PORT_UNUSED", altpll_i.port_clk5 = "PORT_UNUSED", altpll_i.port_clkena0 = "PORT_UNUSED", altpll_i.port_clkena1 = "PORT_UNUSED", altpll_i.port_clkena2 = "PORT_UNUSED", altpll_i.port_clkena3 = "PORT_UNUSED", altpll_i.port_clkena4 = "PORT_UNUSED", altpll_i.port_clkena5 = "PORT_UNUSED", altpll_i.port_extclk0 = "PORT_UNUSED", altpll_i.port_extclk1 = "PORT_UNUSED", altpll_i.port_extclk2 = "PORT_UNUSED", altpll_i.port_extclk3 = "PORT_UNUSED", altpll_i.self_reset_on_loss_lock = "OFF", altpll_i.width_clock = 5;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// meta AXI4 master for testing
|
||||
// AXI4 master for testing
|
||||
// -------------------------------------------------------------------------------------
|
||||
uart2axi4 #(
|
||||
.A_WIDTH ( A_WIDTH )
|
||||
) uart_axi_i (
|
||||
.aresetn ( aresetn ),
|
||||
.aclk ( aclk ),
|
||||
.rstn ( rstn ),
|
||||
.clk ( clk ),
|
||||
.awvalid ( awvalid ),
|
||||
.awready ( awready ),
|
||||
.awaddr ( awaddr ),
|
||||
@ -108,6 +108,7 @@ uart2axi4 #(
|
||||
.uart_rx ( uart_rx )
|
||||
);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// DDR-SDRAM controller
|
||||
// -------------------------------------------------------------------------------------
|
||||
@ -121,10 +122,10 @@ ddr_sdram_ctrl #(
|
||||
.tW2I ( 8'd7 ),
|
||||
.tR2I ( 8'd7 )
|
||||
) ddr_ctrl_i(
|
||||
.rstn_async ( rstn ),
|
||||
.clk ( clk300m ),
|
||||
.aresetn ( aresetn ),
|
||||
.aclk ( aclk ),
|
||||
.rstn_async ( locked ),
|
||||
.drv_clk ( clk300m ),
|
||||
.rstn ( rstn ),
|
||||
.clk ( clk ),
|
||||
.awvalid ( awvalid ),
|
||||
.awready ( awready ),
|
||||
.awaddr ( awaddr ),
|
||||
|
@ -10,8 +10,8 @@ module uart2axi4 #(
|
||||
parameter A_WIDTH = 26,
|
||||
parameter D_WIDTH = 16
|
||||
) (
|
||||
input wire aresetn,
|
||||
input wire aclk,
|
||||
input wire rstn,
|
||||
input wire clk,
|
||||
|
||||
output wire awvalid,
|
||||
input wire awready,
|
||||
@ -83,7 +83,7 @@ reg [ 7:0] wbuf_waddr;
|
||||
reg [D_WIDTH-1:0] wbuf_wdata;
|
||||
reg [ 7:0] wbuf_raddr;
|
||||
wire[ 7:0] wbuf_raddr_n = stat == AXI_W && wready ? wbuf_raddr + 8'd1 : wbuf_raddr;
|
||||
wire[D_WIDTH-1:0] wbuf_rdata;
|
||||
reg [D_WIDTH-1:0] wbuf_rdata;
|
||||
enum logic [3:0] {IDLE, INVALID, GADDR, GRLEN, GWDATA, AXI_AR, AXI_R, AXI_AW, AXI_W, AXI_B} stat;
|
||||
|
||||
assign awvalid = stat == AXI_AW;
|
||||
@ -93,8 +93,8 @@ assign wdata = wbuf_rdata;
|
||||
assign bready = stat == AXI_B;
|
||||
assign arvalid = stat == AXI_AR;
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
awaddr <= '0;
|
||||
awlen <= '0;
|
||||
araddr <= '0;
|
||||
@ -198,36 +198,86 @@ always @ (posedge aclk or negedge aresetn)
|
||||
endcase
|
||||
end
|
||||
|
||||
ram_for_axi4write #(
|
||||
.ADDR_LEN ( 8 ),
|
||||
.DATA_LEN ( D_WIDTH )
|
||||
) ram_for_axi4write_i (
|
||||
.clk ( aclk ),
|
||||
.wr_req ( wbuf_wen ),
|
||||
.wr_addr ( wbuf_waddr ),
|
||||
.wr_data ( wbuf_wdata ),
|
||||
.rd_addr ( wbuf_raddr_n ),
|
||||
.rd_data ( wbuf_rdata )
|
||||
);
|
||||
|
||||
uart_rx#(
|
||||
.CLK_DIV ( 162 ),
|
||||
.CLK_PART ( 6 )
|
||||
) uart_rx_i (
|
||||
.rstn ( aresetn ),
|
||||
.clk ( aclk ),
|
||||
.rx ( uart_rx ),
|
||||
.rvalid ( rx_valid ),
|
||||
.rdata ( rx_data )
|
||||
);
|
||||
|
||||
logic [D_WIDTH-1:0] mem_for_axi4write [256];
|
||||
|
||||
always @ (posedge clk)
|
||||
wbuf_rdata <= mem_for_axi4write[wbuf_raddr_n];
|
||||
|
||||
always @ (posedge clk)
|
||||
if(wbuf_wen)
|
||||
mem_for_axi4write[wbuf_waddr] <= wbuf_wdata;
|
||||
|
||||
|
||||
|
||||
localparam CLK_DIV = 162;
|
||||
localparam CLK_PART = 6;
|
||||
|
||||
reg uart_rx_done = 1'b0;
|
||||
reg [ 7:0] uart_rx_data = 8'h0;
|
||||
reg [ 2:0] uart_rx_supercnt=3'h0;
|
||||
reg [31:0] uart_rx_cnt = 0;
|
||||
reg [ 7:0] uart_rx_databuf = 8'h0;
|
||||
reg [ 5:0] uart_rx_status=6'h0, uart_rx_shift=6'h0;
|
||||
reg uart_rxr=1'b1;
|
||||
wire recvbit = (uart_rx_shift[1]&uart_rx_shift[0]) | (uart_rx_shift[0]&uart_rxr) | (uart_rxr&uart_rx_shift[1]) ;
|
||||
wire [2:0] supercntreverse = {uart_rx_supercnt[0], uart_rx_supercnt[1], uart_rx_supercnt[2]};
|
||||
|
||||
assign rx_valid = uart_rx_done;
|
||||
assign rx_data = uart_rx_data;
|
||||
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn)
|
||||
uart_rxr <= 1'b1;
|
||||
else
|
||||
uart_rxr <= uart_rx;
|
||||
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
uart_rx_done <= 1'b0;
|
||||
uart_rx_data <= 8'h0;
|
||||
uart_rx_status <= 6'h0;
|
||||
uart_rx_shift <= 6'h0;
|
||||
uart_rx_databuf <= 8'h0;
|
||||
uart_rx_cnt <= 0;
|
||||
end else begin
|
||||
uart_rx_done <= 1'b0;
|
||||
if( (supercntreverse<CLK_PART) ? (uart_rx_cnt>=CLK_DIV) : (uart_rx_cnt>=CLK_DIV-1) ) begin
|
||||
if(uart_rx_status==0) begin
|
||||
if(uart_rx_shift == 6'b111_000)
|
||||
uart_rx_status <= 1;
|
||||
end else begin
|
||||
if(uart_rx_status[5] == 1'b0) begin
|
||||
if(uart_rx_status[1:0] == 2'b11)
|
||||
uart_rx_databuf <= {recvbit, uart_rx_databuf[7:1]};
|
||||
uart_rx_status <= uart_rx_status + 5'b1;
|
||||
end else begin
|
||||
if(uart_rx_status<62) begin
|
||||
uart_rx_status <= 62;
|
||||
uart_rx_data <= uart_rx_databuf;
|
||||
uart_rx_done <= 1'b1;
|
||||
end else begin
|
||||
uart_rx_status <= uart_rx_status + 6'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
uart_rx_shift <= {uart_rx_shift[4:0], uart_rxr};
|
||||
uart_rx_supercnt <= uart_rx_supercnt + 3'h1;
|
||||
uart_rx_cnt <= 0;
|
||||
end else
|
||||
uart_rx_cnt <= uart_rx_cnt + 1;
|
||||
end
|
||||
|
||||
|
||||
|
||||
axis2uarttx #(
|
||||
.CLK_DIV ( 651 ),
|
||||
.DATA_WIDTH ( D_WIDTH ),
|
||||
.FIFO_ASIZE ( 10 )
|
||||
) uart_tx_i (
|
||||
.aresetn ( aresetn ),
|
||||
.aclk ( aclk ),
|
||||
.rstn ( rstn ),
|
||||
.clk ( clk ),
|
||||
.tvalid ( rvalid ),
|
||||
.tready ( rready ),
|
||||
.tlast ( rlast ),
|
||||
@ -242,136 +292,20 @@ endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module ram_for_axi4write #(
|
||||
parameter ADDR_LEN = 12,
|
||||
parameter DATA_LEN = 8
|
||||
) (
|
||||
input logic clk,
|
||||
input logic wr_req,
|
||||
input logic [ADDR_LEN-1:0] rd_addr, wr_addr,
|
||||
output logic [DATA_LEN-1:0] rd_data,
|
||||
input logic [DATA_LEN-1:0] wr_data
|
||||
);
|
||||
|
||||
localparam RAM_SIZE = (1<<ADDR_LEN);
|
||||
|
||||
logic [DATA_LEN-1:0] mem [RAM_SIZE];
|
||||
|
||||
initial rd_data = 0;
|
||||
|
||||
always @ (posedge clk)
|
||||
rd_data <= mem[rd_addr];
|
||||
|
||||
always @ (posedge clk)
|
||||
if(wr_req)
|
||||
mem[wr_addr] <= wr_data;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module uart_rx #(
|
||||
parameter CLK_DIV = 108, // UART baud rate = clk freq/(4*CLK_DIV)
|
||||
// modify CLK_DIV to change the UART baud
|
||||
// for example, when clk=50MHz, CLK_DIV=108, then baud=100MHz/(4*108)=115200
|
||||
// 115200 is a typical baud rate for UART
|
||||
parameter CLK_PART = 4 // from 0 to 7
|
||||
) (
|
||||
input wire clk, rstn,
|
||||
// uart rx input
|
||||
input wire rx,
|
||||
// user interface
|
||||
output wire rvalid,
|
||||
output wire [7:0] rdata
|
||||
);
|
||||
|
||||
reg done = 1'b0;
|
||||
reg [ 7:0] data = 8'h0;
|
||||
reg [ 2:0] supercnt=3'h0;
|
||||
reg [31:0] cnt = 0;
|
||||
reg [ 7:0] databuf = 8'h0;
|
||||
reg [ 5:0] status=6'h0, shift=6'h0;
|
||||
reg rxr=1'b1;
|
||||
wire recvbit = (shift[1]&shift[0]) | (shift[0]&rxr) | (rxr&shift[1]) ;
|
||||
wire [2:0] supercntreverse = {supercnt[0], supercnt[1], supercnt[2]};
|
||||
|
||||
assign rvalid = done;
|
||||
assign rdata = data;
|
||||
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn)
|
||||
rxr <= 1'b1;
|
||||
else
|
||||
rxr <= rx;
|
||||
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
done <= 1'b0;
|
||||
data <= 8'h0;
|
||||
status <= 6'h0;
|
||||
shift <= 6'h0;
|
||||
databuf <= 8'h0;
|
||||
cnt <= 0;
|
||||
end else begin
|
||||
done <= 1'b0;
|
||||
if( (supercntreverse<CLK_PART) ? (cnt>=CLK_DIV) : (cnt>=CLK_DIV-1) ) begin
|
||||
if(status==0) begin
|
||||
if(shift == 6'b111_000)
|
||||
status <= 1;
|
||||
end else begin
|
||||
if(status[5] == 1'b0) begin
|
||||
if(status[1:0] == 2'b11)
|
||||
databuf <= {recvbit, databuf[7:1]};
|
||||
status <= status + 5'b1;
|
||||
end else begin
|
||||
if(status<62) begin
|
||||
status <= 62;
|
||||
data <= databuf;
|
||||
done <= 1'b1;
|
||||
end else begin
|
||||
status <= status + 6'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
shift <= {shift[4:0], rxr};
|
||||
supercnt <= supercnt + 3'h1;
|
||||
cnt <= 0;
|
||||
end else
|
||||
cnt <= cnt + 1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module axis2uarttx #(
|
||||
parameter CLK_DIV = 434,
|
||||
parameter DATA_WIDTH = 32,
|
||||
parameter FIFO_ASIZE = 8
|
||||
) (
|
||||
// AXI-stream (slave) side
|
||||
input logic aclk, aresetn,
|
||||
input logic tvalid, tlast,
|
||||
output logic tready,
|
||||
input logic rstn,
|
||||
input logic clk,
|
||||
input logic tvalid,
|
||||
input logic tlast,
|
||||
output logic tready,
|
||||
input logic [DATA_WIDTH-1:0] tdata,
|
||||
// UART TX signal
|
||||
output logic uart_tx
|
||||
output logic uart_tx
|
||||
);
|
||||
localparam TX_WIDTH = (DATA_WIDTH+3) / 4;
|
||||
|
||||
@ -390,30 +324,30 @@ logic [DATA_WIDTH-1:0] fifo_data;
|
||||
logic endofline = 1'b0;
|
||||
logic [TX_WIDTH*4-1:0] data='0;
|
||||
wire emptyn = (fifo_rpt != fifo_wpt);
|
||||
assign tready = (fifo_rpt != fifo_wpt_next) & aresetn;
|
||||
assign tready = (fifo_rpt != fifo_wpt_next) & rstn;
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn)
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn)
|
||||
uart_tx <= 1'b1;
|
||||
else begin
|
||||
uart_tx <= uart_txb;
|
||||
end
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn)
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn)
|
||||
fifo_wpt <= '0;
|
||||
else begin
|
||||
if(tvalid & tready) fifo_wpt <= fifo_wpt_next;
|
||||
end
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn)
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn)
|
||||
cyccnt <= 0;
|
||||
else
|
||||
cyccnt <= (cyccnt<CLK_DIV-1) ? cyccnt+1 : 0;
|
||||
|
||||
always @ (posedge aclk or negedge aresetn)
|
||||
if(~aresetn) begin
|
||||
always @ (posedge clk or negedge rstn)
|
||||
if(~rstn) begin
|
||||
fifo_rpt <= '0;
|
||||
endofline <= 1'b0;
|
||||
data <= '0;
|
||||
@ -453,48 +387,14 @@ always @ (posedge aclk or negedge aresetn)
|
||||
end
|
||||
end
|
||||
|
||||
ram_for_axi_stream_to_uart_tx_fifo #(
|
||||
.ADDR_LEN ( FIFO_ASIZE ),
|
||||
.DATA_LEN ( DATA_WIDTH + 1 )
|
||||
) ram_for_uart_tx_fifo_inst (
|
||||
.clk ( aclk ),
|
||||
.wr_req ( tvalid & tready ),
|
||||
.wr_addr ( fifo_wpt ),
|
||||
.wr_data ( {tlast, tdata} ),
|
||||
.rd_addr ( fifo_rpt ),
|
||||
.rd_data ( {fifo_tlast,fifo_data} )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module ram_for_axi_stream_to_uart_tx_fifo #(
|
||||
parameter ADDR_LEN = 12,
|
||||
parameter DATA_LEN = 8
|
||||
) (
|
||||
input logic clk,
|
||||
input logic wr_req,
|
||||
input logic [ADDR_LEN-1:0] rd_addr, wr_addr,
|
||||
output logic [DATA_LEN-1:0] rd_data,
|
||||
input logic [DATA_LEN-1:0] wr_data
|
||||
);
|
||||
|
||||
localparam RAM_SIZE = (1<<ADDR_LEN);
|
||||
|
||||
logic [DATA_LEN-1:0] mem [RAM_SIZE];
|
||||
|
||||
initial rd_data = 0;
|
||||
logic [DATA_WIDTH:0] mem_for_axi_stream_to_uart_tx_fifo [1<<FIFO_ASIZE];
|
||||
|
||||
always @ (posedge clk)
|
||||
rd_data <= mem[rd_addr];
|
||||
{fifo_tlast, fifo_data} <= mem_for_axi_stream_to_uart_tx_fifo[fifo_rpt];
|
||||
|
||||
always @ (posedge clk)
|
||||
if(wr_req)
|
||||
mem[wr_addr] <= wr_data;
|
||||
if(tvalid & tready)
|
||||
mem_for_axi_stream_to_uart_tx_fifo[fifo_wpt] <= {tlast, tdata};
|
||||
|
||||
endmodule
|
||||
|
||||
|
@ -51,7 +51,6 @@ set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "2.5 V"
|
||||
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE RTL/top.sv
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE RTL/uart2axi4.sv
|
||||
set_global_assignment -name VERILOG_FILE RTL/pll.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE ../RTL/ddr_sdram_ctrl.sv
|
||||
|
||||
set_location_assignment PIN_23 -to clk50m
|
||||
|
Loading…
x
Reference in New Issue
Block a user