求解关于一道笔试题,用Verilog编一个接口转换电路
求解啊
按照你的思路,不知道写的对不对,麻烦能给看一下吗,谢谢了。
module(da,wra_n,clka,clkb,rst_n,wrb,db); input da,clka,clkb,rst_n,wra_n;
output srb;
output [7:0] db;
reg [7:0] r,po,q1_db;
wire [7:0] q2_db;
always@(posedge clka or negedge rst_n)
if(!rst_n)
r<=0;
else if (wra_n)
r<={r,da};
[p=154, 2, left]assign
assign po=(wra_n)? r:8'b0;
always@(posedge clkb or negedge rst_n)
if(!rst_n)
{q2_db,q1_db}<=0;
else begin
{q2_db,q1_db}<={q1_db,po};
wrb<=1;
end
assign db<=q2_db;
endmodule
让您见笑了,没什么经验,那怎么改啊?
我写了一个,希望能够指正
module convert(
da,
wra_n,
clka,
clkb,
rst_n,
wrb,
db);
input da,clka,clkb,rst_n,wra_n;
output srb;
output [7:0] db;
reg [2:0] cnt;
reg [7:0] db_reg;
assign db=wrb?db_reg:0;
always@(posedge clka or negedge rst_n)
if(~rst_n) begin
cnt<=0;
db_reg<=0;
end
else if(~wra_n) begin
cnt<=cnt+1;
case(cnt)
3'd0:db_reg[0]<=da;
3'd1:db_reg[1]<=da;
3'd2:db_reg[2]<=da;
3'd3:db_reg[3]<=da;
3'd4:db_reg[4]<=da;
3'd5:db_reg[5]<=da;
3'd6:db_reg[6]<=da;
3'd7:db_reg[7]<=da;
default:;
endcase
end
always@(posedge clkb or negedge rst_n)
if(~rst_n)
wrb<=0;
else if(wra_n && cnt==0)
wrb<=1;
else if(wrb)
wrb<=0;
endmodule
1,做存储电路,在clka domain中,将wr_a有效时的数据latch下来,共8个period。
2,时钟转换电路,建议用handshake来做。clka domain采集到到8个bit的的时候将数据hold住,将ready信号发送到clockb domain。clkb 看到clka发送过来的数据后采集数据,一个周期后回执ready_down信号。
3,clka domain收到clkb发过来的ready_down信号后释放数据和counter。
小编描述得很全面啊,要是能把verilog贴上来就更好了
第二三点能理解,但是第一点中“把什么什么latch下来”的说法有点不理解,是指用锁存器作为存储器?
经你指点,前面把串数据保存下来改成这样:
always@(posedge clka or negedge rst_n)
if(~rst_n)
db_reg<=0;
else if(~wra_n)
db_reg<=db_pre;
end
assign db_pre={db_reg[6:0],da};
异步处理的时序如果按照题目的图所示,就是你说的“在对wra_n取沿之前锁存两次。” 我感觉不是很明白,具体应该怎么做?
module memi(da,wra_n,clka,clkb,rst_n,wrb,db);input da,wra_n,clka,clkb,rst_n;
output wrb;
output[7:0] db;
reg wra_1,wra_2;
reg wrb;
reg[7:0] db;
reg[7:0] data;
always@(posedge clka or negedge rst_n)
if(!rst_n)
data<=8'b0;
else if(!wra_n)
data<={data[6:0],da};
always@(posedge clkb)
begin
wra_1<=wra_n;
wra_2<=wra_1;
end
assign wra_rising=wra_1&(!wra_2);
always@(posedge clkb)
if(wra_rising)
begin
db<=data;
wrb<=1;
end
else
begin
db<=8'hxx;
wrb<=0;
end
endmodule
是这个意思吗?
串并转换及并行数据锁存部分ok
不过后面的时序还是要仔细斟酌。
这个代码,wr_b和db[7:0]相对于原始数据,latency满足不了要求(要求是只有2clka的latency)
可以通过仿真的方式,稍微调整就全部ok了
“wra足够长” 不等于 “wra的间隔” 足够长!
而且wrb&db[7:0]和wra的时序关系,图上已经给定了,似乎跟题目的文字描述没有冲突的地方?
它是慢时钟域到快时钟域,这样打两拍可以吧?
assign wra_rising=wra_1&(!wra_2);这句是不是延迟一个周期的作用啊?
另外不写这句能正常实现功能吗?
主要是跨时钟域的处理吧,将信号同步到clkb时钟域,采用打两拍的方式。
8楼说的不错,很系统
不能直接做同步,要考虑到2个时钟域的频率差异。不是所有的异步都是打两拍就可以搞定的。
请指教啊!
是典型的异步处理电路。
1、需要完成串并转换,2、在最后一bit D0传输完毕后,寄存输出wra_n的上升沿,在clkb打2拍(这种情况适合clka频率比clkb小的条件下,LZ给的图中文字说明是时钟示意图不一致),3、采样2-DFF同步器输出信号为1,同时采样串并转换输出信号;
飘过啊啊
- //------------------------------------------------------------------------------
- always @(posedge clka or negedge rst_n) begin
- if(~rst_n) da_buff <= 8'b0 ;
- else if(~wra_n) da_buff <= {da_buff[6:0], da} ;
- end
- //------------------------------------------------------------------------------
- always @(posedge clkb or negedge rst_n) begin
- if(~rst_n) db_buff <= 8'b0 ;
- else db_buff <= da_buff ;
- end
- always @(posedge clkb or negedge rst_n) begin
- if(~rst_n) wrb_syn <= 2'b11 ;
- else wrb_syn <= {wrb_syn[0], wra_n} ;
- end
- assign db = db_buff;
- assign wrb = ~wrb_syn[1] & wrb_syn[0];
再有 图中的wra_n到wrb的时钟只差了一个 我觉得只能用1拍的同步器 不能用两拍的同步器完成
故而代码如上
这里没明白1拍的同步器和2拍的同步器是什么?
----------------------------------------------------------------------
我觉得只能用1拍的同步器 不能用两拍的同步器完成故而代码如上
说一个问题。从图上来看,采集da的数据用clka的下降沿比较好。不过这涉及到具体应用了,但从题目上来说上升沿也OK
你看看我这个代码对不?
module top
(
input clka,
input clkb,
input rst_n,
input wra_n,
input da,
output wrb,
output [7:0]db
);
// =============== Main Code Start ===============
reg [7:0]mem_p;
reg [7:0]mem_r;
always@(*)
begin:ac_clka_shifter
mem_p = mem_r;
if(!wra_n) begin
mem_p = {mem_r[6:0],da};
end
end
always@(posedge clka or negedge rst_n)
begin:as_mem_update
if(!rst_n) begin
mem_r <= 8'h00;
end
else begin
mem_r <= mem_p;
end
end
reg wra_r1;
reg wra_r2;
always@(posedge clkb or negedge rst_n)
begin:as_sync
if(!rst_n) begin
wra_r1 <= 1;
wra_r2 <= 1;
end
else begin
wra_r1 <= wra_n;
wra_r2 <= wra_r1;
end
end
assign wrb = (wra_r1 & !wra_r2);
assign db = wrb ? mem_r : 8'hzz;
endmodule
教科书写法,严格的组合逻辑和时序逻辑分开。
另外请教一个问题:
第一个组合逻辑,没有else分支?这种写法能否OK?
我看错了,if前面有赋值语句,不会有问题。相当于else。
请教一个问题,在wra_n上升沿之前的锁存两次怎么实现?
看了大家的回复,我感觉大部分都只是注重了锁存,而是没有关注wrb上升沿之前的那两次锁存。特请教一下。
试着写了一个,没有功能仿真
reg [7:0] db;
reg [2:0] cnt3bit_a;
reg [2:0] dvalid_a;
wire dvalid_a;
reg wr_b;
// a 时钟域
always @ (posedge clka or negedge rst_n) begin
if(~rst_n)
cnt3bit_a <= 0;
else if(cnt3bit_a == 3'd7)
cnt3bit_a <= 0;
else if(~wra_n)
cnt3bit_a <= cnt3bit_a + 1;
end
always @ (posedge clka or negedge rst_n) begin
if(~rst_n)
db <= 0;
else if(~wra_n)
db <= {db[6:0],da};
end
// 快到慢 打拍
always @ (posedge clka or negedge rst_n) begin
if(~rst_n)
dvalid_a <= 0;
else if(wr_b) // b 时钟域信号
dvalid_a <= 0;
else if(cnt3bit_a == 3'd7)
dvalid_a[0] <= 1'b1;
else if(|dvalid_a)
dvalid_a << 1;
end
chen851112 异步时钟域取上升沿的方法很好
你没有用到clkb?我赶脚32楼写的是最正式的。
呵呵,讨论的好热烈
