微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 求解关于一道笔试题,用Verilog编一个接口转换电路

求解关于一道笔试题,用Verilog编一个接口转换电路

时间:10-02 整理:3721RD 点击:



求解啊


按照你的思路,不知道写的对不对,麻烦能给看一下吗,谢谢了。
   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,同时采样串并转换输出信号;


飘过啊啊

  1. //------------------------------------------------------------------------------
  2. always @(posedge clka or negedge rst_n) begin
  3.     if(~rst_n)          da_buff     <=  8'b0                ;
  4.     else if(~wra_n)     da_buff     <=  {da_buff[6:0], da}  ;
  5. end
  6. //------------------------------------------------------------------------------
  7. always @(posedge clkb or negedge rst_n) begin
  8.     if(~rst_n)          db_buff     <=  8'b0                ;
  9.     else                db_buff     <=  da_buff             ;
  10. end
  11. always @(posedge clkb or negedge rst_n) begin
  12.     if(~rst_n)          wrb_syn     <=  2'b11               ;
  13.     else                wrb_syn     <=  {wrb_syn[0], wra_n} ;
  14. end
  15. assign  db  =   db_buff;
  16. assign  wrb =   ~wrb_syn[1] & wrb_syn[0];

复制代码

如果不是图中db是按照clkb变化的话db_buffer都不需要 只要控制好wrb就可以是数据正确的传输到clkb时钟域
再有 图中的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楼写的是最正式的。

呵呵,讨论的好热烈

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top