很经典的手撕题,这道题要求产生的格雷码要在本时钟域中打一拍,其实不打也没关系。

主要要记住
1、bin2gray的方法:右移一位与移位前异或;
2、格雷码比较方法:空:读指针格雷码和写指针同步过来的格雷码相同;满:写指针格雷码高两位与读指针同步过来的格雷码正好相反,低位相同。
`timescale 1ns/1ns
/***************************************RAM*****************************************/
module dual_port_RAM #(parameter DEPTH = 16,
parameter WIDTH = 8)(
input wclk
,input wenc
,input [$clog2(DEPTH)-1:0] waddr //深度对2取对数,得到地址的位宽。
,input [WIDTH-1:0] wdata //数据写入
,input rclk
,input renc
,input [$clog2(DEPTH)-1:0] raddr //深度对2取对数,得到地址的位宽。
,output reg [WIDTH-1:0] rdata //数据输出
);
reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];
always @(posedge wclk) begin
if(wenc)
RAM_MEM[waddr] <= wdata;
end
always @(posedge rclk) begin
if(renc)
rdata <= RAM_MEM[raddr];
end
endmodule
/***************************************AFIFO*****************************************/
module asyn_fifo#(
parameter WIDTH = 8,
parameter DEPTH = 16
)(
input wclk ,
input rclk ,
input wrstn ,
input rrstn ,
input winc ,
input rinc ,
input [WIDTH-1:0] wdata ,
output wire wfull ,
output wire rempty ,
output wire [WIDTH-1:0] rdata
);
parameter ADDR_WIDTH = $clog2(DEPTH);
reg [ADDR_WIDTH:0]waddr,raddr;//多一位用于比较空满
always@(posedge wclk or negedge wrstn)
begin
if(~wrstn)
waddr <= 'd0;
else if(winc&&~wfull)
waddr <= waddr + 1;
end
always@(posedge rclk or negedge rrstn)
begin
if(~rrstn)
raddr <= 'd0;
else if(rinc&&~rempty)
raddr <= raddr + 1;
end
reg [ADDR_WIDTH:0]waddr_gray,raddr_gray;//格雷码
reg [ADDR_WIDTH:0]waddr_gray_sync1,raddr_gray_sync1;//打一拍后
reg [ADDR_WIDTH:0]waddr_gray_sync2,raddr_gray_sync2;//打两拍后
/*bin2gray*/
// always@(*)
// begin
// waddr_gray = (waddr>>1)^waddr;
// raddr_gray = (raddr>>1)^raddr;
// end
always@(posedge wclk or negedge wrstn)
begin
if(~wrstn)
waddr_gray <= 'd0;
else
waddr_gray <= (waddr>>1)^waddr;
end
always@(posedge rclk or negedge rrstn)
begin
if(~rrstn)
raddr_gray <= 'd0;
else
raddr_gray <= (raddr>>1)^raddr;
end
/*把格雷码打两拍传输*/
always@(posedge wclk or negedge wrstn)
begin
if(~wrstn)begin
raddr_gray_sync1 <= 'd0;
raddr_gray_sync2 <= 'd0;
end else begin
raddr_gray_sync1 <= raddr_gray;
raddr_gray_sync2 <= raddr_gray_sync1;
end
end
always@(posedge rclk or negedge rrstn)
begin
if(~rrstn)begin
waddr_gray_sync1 <= 'd0;
waddr_gray_sync2 <= 'd0;
end else begin
waddr_gray_sync1 <= waddr_gray;
waddr_gray_sync2 <= waddr_gray_sync1;
end
end
/*空满判断*/
assign wfull = (waddr_gray[ADDR_WIDTH:ADDR_WIDTH-1]==~raddr_gray_sync2[ADDR_WIDTH:ADDR_WIDTH-1])&&(waddr_gray[ADDR_WIDTH-2:0]==raddr_gray_sync2[ADDR_WIDTH-2:0]);
assign rempty = (raddr_gray==waddr_gray_sync2);
dual_port_RAM #(.WIDTH(WIDTH),.DEPTH(DEPTH))
U0(
.wclk(wclk),
.wenc(winc&&~wfull),
.waddr(waddr[ADDR_WIDTH-1:0]),
.wdata(wdata),
.rclk(rclk),
.renc(rinc&&~rempty),
.raddr(raddr[ADDR_WIDTH-1:0]),
.rdata(rdata) );
endmodule
比异步FIFO简单多了。不过感觉有问题,满之后过一个周期才会输出满。
`timescale 1ns/1ns
/**********************************RAM************************************/
module dual_port_RAM #(parameter DEPTH = 16,
parameter WIDTH = 8)(
input wclk
,input wenc
,input [$clog2(DEPTH)-1:0] waddr //深度对2取对数,得到地址的位宽。
,input [WIDTH-1:0] wdata //数据写入
,input rclk
,input renc
,input [$clog2(DEPTH)-1:0] raddr //深度对2取对数,得到地址的位宽。
,output reg [WIDTH-1:0] rdata //数据输出
);
reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];
always @(posedge wclk) begin
if(wenc)
RAM_MEM[waddr] <= wdata;
end
always @(posedge rclk) begin
if(renc)
rdata <= RAM_MEM[raddr];
end
endmodule
/**********************************SFIFO************************************/
module sfifo#(
parameter WIDTH = 8,
parameter DEPTH = 16
)(
input clk ,
input rst_n ,
input winc ,
input rinc ,
input [WIDTH-1:0] wdata ,
output reg wfull ,
output reg rempty ,
output wire [WIDTH-1:0] rdata
);
parameter ADDR_WIDTH = $clog2(DEPTH);
reg [ADDR_WIDTH:0]waddr,raddr;//多一位用于比较空满
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
waddr <= 'd0;
else if(winc&&~wfull)
waddr <= waddr + 1;
end
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
raddr <= 'd0;
else if(rinc&&~rempty)
raddr <= raddr + 1;
end
/*空满判断*/
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)begin
wfull <= 'd0;
rempty <= 'd0;
end else begin
wfull <= (waddr[ADDR_WIDTH]==~raddr[ADDR_WIDTH])&&(waddr[ADDR_WIDTH-1:0]==raddr[ADDR_WIDTH-1:0]);
rempty <= (raddr==waddr);
end
end
dual_port_RAM #(.WIDTH(WIDTH),.DEPTH(DEPTH))
U0(
.wclk(clk),
.wenc(winc&&~wfull),
.waddr(waddr[ADDR_WIDTH-1:0]),
.wdata(wdata),
.rclk(clk),
.renc(rinc&&~rempty),
.raddr(raddr[ADDR_WIDTH-1:0]),
.rdata(rdata) );
endmodule
参考之前看《硬件架构的艺术》写的代码【《硬件架构的艺术》读书笔记】03 处理多个时钟(2) - Magnolia666 - 博客园 (cnblogs.com)
可以提前一个周期输出空满,更合理。
垃圾题目,每两个周期加一次,看了一下题解,感觉确实用状态机更有道理,我这样写本质还是一个二进制计数器。
`timescale 1ns/1ns
module gray_counter(
input clk,
input rst_n,
output reg [3:0] gray_out
);
reg [3:0]bin;
reg flag;
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
flag <= 0;
else
flag <= ~flag;
end
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
bin <= 0;
else
bin <= flag?bin + 1:bin;
end
always@(*)
begin
gray_out = (bin>>1)^bin;
end
endmodule
题目大概意思是通过MUX把四位数据从时钟域a同步到时钟域b。感觉怪怪的。。。。
看了一下要把数据和使能在时钟域a打一拍,再把使能信号在时钟域b打两拍控制MUX选通data信号。
`timescale 1ns/1ns
module mux(
input clk_a ,
input clk_b ,
input arstn ,
input brstn ,
input [3:0] data_in ,
input data_en ,
output reg [3:0] dataout
);
reg [3:0]data_in_rega;
reg data_en_rega;
always@(posedge clk_a or negedge arstn)
begin
if(~arstn)begin
data_en_rega <= 0;
data_in_rega <= 0;
end else begin
data_en_rega <= data_en;
data_in_rega <= data_in;
end
end
reg data_en_regb1;
reg data_en_regb2;
always@(posedge clk_b or negedge brstn)
begin
if(~brstn)begin
data_en_regb1 <= 0;
data_en_regb2 <= 0;
end else begin
data_en_regb1 <= data_en_rega;
data_en_regb2 <= data_en_regb1;
end
end
always@(posedge clk_b or negedge brstn)
begin
if(~brstn)begin
dataout <= 0;
end else begin
dataout <= data_en_regb2?data_in_rega:dataout;
end
end
endmodule
邸志雄的课里看到过,参考芯动力——硬件加速设计方法_西南交通大学_中国大学MOOC(慕课) (icourse163.org)

`timescale 1ns/1ns
module pulse_detect(
input clk_fast ,
input clk_slow ,
input rst_n ,
input data_in ,
output dataout
);
reg toggle;
always@(posedge clk_fast or negedge rst_n)
begin
if(~rst_n)
toggle <= 1'b0;
else
toggle <= data_in?(~toggle):toggle;
end
reg data_syn0,data_syn1,data_syn2;
always@(posedge clk_slow or negedge rst_n)
begin
if(~rst_n)begin
data_syn0 <= 1'b0;
data_syn1 <= 1'b0;
data_syn2 <= 1'b0;
end else begin
data_syn0 <= toggle;
data_syn1 <= data_syn0;
data_syn2 <= data_syn1;
end
end
assign dataout = data_syn2^data_syn1;
endmodule
1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析: 在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1: print(k)k=k/2A.1000 B.10C.11D.9解析: 按照题意每次循环K/2,直到K值小于等
我正在尝试下载一个大文件,然后使用Ruby将该文件发布到REST端点。该文件可能非常大,即超过可以存储在内存中甚至磁盘上的临时文件中的容量。我一直在用Net::HTTP尝试这个,但我愿意接受任何其他库(rest-client等)的解决方案,只要他们做我想做的事情。这是我尝试过的:require'net/http'source_uri=URI("https://example.org/very_large_file")source_request=Net::HTTP::Get.new(source_uri)source_http=Net::HTTP.start(source_uri.ho
我在Heroku上构建了一个必须在Docker容器内运行的RoR应用程序。为此,我使用officialDockerfile.因为它在Heroku中很常见,所以我需要一些附加组件才能使这个应用程序完全运行。在生产中,变量DATABASE_URL在我的应用程序中可用。但是,如果我尝试其他一些使用环境变量(在我的例子中是Mailtrap)的加载项,变量不会在运行时复制到实例中。所以我的问题很简单:如何让docker实例在Heroku上执行时知道环境变量?您可能会问,我已经知道我们可以在docker-compose.yml中指定一个environment指令。我想避免这种情况,以便能够通过项目
FPGA时钟和时钟域时钟树所谓时钟树为FPGA内部资源,分:全局时钟树,区域时钟树,IO时钟树原则上优先使用全局时钟树,在GT接口上使用IO时钟树,一般工具也会对GT时钟加以限制;时钟树使用方式正确的物理连接FPGA会由物理管脚专门用于全局时钟设置,通过查询数据手册可以在PCB设计阶段进行确认,当外部时钟接入此管脚时,工具会自动占有全局时钟树资源,当接入普通信号时不会分配时钟树资源;恰当的代码描述原语的使用,即BUFG的使用,可以将PLL的输出等内部时钟进行全局时钟资源的分配;IO时钟资源需要参考相应接口手册,以ultrascale的GTH为例,其JESD204的时钟方案针对不同的子类会由不同
似乎Capistrano曾经有anextensivefiletransferpackage.但是在3.0版本重写后好像没有了。知道是否还有其他方法可以将文件传输到服务器/从服务器传输文件吗? 最佳答案 下载:desc"downloadfoobar.txtintolocal_dir/"task:foobardodownload!"some_remote_path/foobar.txt","local_dir/"end我知道这从Cap3.2.1开始有效,因为我现在正在使用它。 关于ruby-
我正在尝试将数据从我的生产数据库传输到我的登台数据库,但没有成功。我正在关注heroku的相关文档:http://devcenter.heroku.com/articles/pgbackups#transfers这些是我运行的命令...$herokuaddons:addpgbackups--remotestaging$herokuaddons:addpgbackups--remoteproduction$herokupgbackups:capture--remoteproduction$herokupgbackups:restoreDATABASE`herokupgbackups:ur
从命令行scp实用程序的功能来看,SCP上传速度似乎在库中受到很大限制。我知道这是Ruby(1.9.2-p0),但是Net::SCP比Linux实用程序慢大约8倍(使用大文件看到...见下文)。我很好奇知道(我快速查看了代码)这是否是Ruby中套接字的方式,或者是否可以更好地多路复用Net::SCP套接字?我注意到无论我尝试哪种上传方式(串行上传、异步操作channel、使用scp对象的多个实例)我都无法在SCP上传上获得超过9兆字节/秒的传输速度。现在……让我解释一下我调查的细节:1)尝试不同的加密算法我使用了不同类型的加密,速度没有太大变化示例:我可以使用命令行scp(加密算法=a
我正在寻找一种从AmazonS3动态流式下载zip文件的方法。应用程序托管在EC2上,文件存储在S3上。需要让用户能够从一组文件中进行选择,然后将这些文件打包并下载给他们。听说过一些可能可行的Actionscript库(aszip和fzip),或者可以在Ruby或什至PHP中执行此操作。文件不需要任何压缩,zip只是用于将文件捆绑到一个下载中.... 最佳答案 我使用NginxZipModule流式传输本地文件,但可以选择从远程位置流式传输。否则,您可以将它与VFS安装的S3存储一起用作本地文件系统。支持seek-断点续传和加速下载
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录一、设计原理1.DS1302介绍2.闹钟音乐播放原理二、程序设计1.DS1302.h2.ds1302.c3.music.h4.main.c三、电路图四、运行结果1.proteus仿真2.开发板实验五、总结六、附件提示:以下是本篇文章正文内容,下面案例可供参考一、设计原理1.DS1302介绍DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。该芯片采用普通32.768kHz晶振,DS1302工作时功耗很
我正在尝试在Rails控制台中执行以下代码:ce=Curl::Easy.new("http://www.homestolove.com.au/bathroom-profile-fresh-approach-2391")ce.verbose=truece.perform但我收到以下错误。谁能建议如何解决这个问题?看起来这个url返回响应的速度很慢。在文件传输完成之前,我们可以做些什么来阻止连接终止吗?*Addinghandle:conn:0x95f3210*Addinghandle:send:0*Addinghandle:recv:0*Curl_addHandleToPipeline:l