日常记录(75)FiFo与基础内容
异步FIFO
https://gitee.com/bai-mengwei/asyn_fifo/tree/master/dut
最重要的是同步时钟域和亚稳态,是使用非阻塞赋值(两级D触发器实现的)
功能点分为:
存储体本身
always @(posedge rclk) begin
if (rclk_en) begin
rdata <= MEM[raddr];
end
end
always @(posedge wclk) begin
if (wclk_en) begin
MEM[waddr] <= wdata;
end
end
空状态判断
读格雷码指针和从读时钟域获取到的写指针相同,则为空。
always @(posedge rclk or negedge rrst_n) begin
if (!rrst_n) begin
rempty <= 1;
end else begin
rempty <= (rgnext==rwptr2);
end
end
满状态判断
三个条件:首位不同,前两位异或值相同,除前两位相同。
assign w_2ndmsb = wgnext[ADDRSIZE] ^ wgnext[ADDRSIZE-1];
assign wr_2ndmsb = wrptr2[ADDRSIZE] ^ wrptr2[ADDRSIZE-1];
always @(posedge wclk or negedge wrst_n) begin
if (!wrst_n) begin
wfull <= 0;
end else begin
wfull <= (wgnext[ADDRSIZE] !== wrptr2[ADDRSIZE]) && (w_2ndmsb==wr_2ndmsb)
&& (wgnext[ADDRSIZE-2:0] == wrptr2[ADDRSIZE-2:0]);
end
end
读时钟域同步
D触发器获得写指针。(从读时钟域)
always @(posedge rclk or negedge rrst_n) begin
if (!rrst_n) begin
{rwptr2, rwptr1} <= 0;
end else begin
{rwptr2, rwptr1} <= {rwptr1, wptr};
end
end
写时钟域同步
同理在写时钟域获得读指针。
always @(posedge wclk or negedge wrst_n) begin
if (!wrst_n) begin
{wrptr2, wrptr1} <= 0;
end else begin
{wrptr2, wrptr1} <= {wrptr1, rptr};
end
end
顶层集成
sync_r2w sync_r2w(.wrptr2(wrptr2), .rptr(rptr), .wclk(wclk), .wrst_n(wrst_n));
sync_w2r sync_w2r(.rwptr2(rwptr2), .wptr(wptr), .rclk(rclk), .rrst_n(rrst_n));
fifomem fifomem(.wdata(wdata), .rdata(rdata), .raddr(raddr), .waddr(waddr),
.rclk(rclk), .wclk(wclk), .rclk_en(rinc), .wclk_en(winc));
rptr_empty rptr_empty(.rempty(rempty), .raddr(raddr), .rptr(rptr), .rwptr2(rwptr2),
.rinc(rinc), .rclk(rclk), .rrst_n(rrst_n));
wptr_full wptr_full(.wfull(wfull), .waddr(waddr), .wptr(wptr), .wrptr2(wrptr2),
.winc(winc), .wclk(wclk), .wrst_n(wrst_n));
数组操作
$time的数据类型
time类型,64位无符号,4状态的变量。
$isunknown函数
需要和if、== 1配合使用,否则可能失败。用于检测变量是z或者x。
而直接检测变量是z或者x的===号,需要声明出对应为位数,即1'bx等。
数组元素的操作
- 值全为1的方式可以使用default,但是需要单独使用。我这里。
- 值全为1的方式也可以使用'{n{number}}的方式,但是要确定n的个数是数组元素的个数。
- 合并数组的单个索引,可以使用单个赋值操作。但是连续赋值操作失效。
- 确定数组中的元素可以使用$size
- 队列$insert可以在索引前插入数字,但是不能使用default赋值。
- 求和,积等内部的方法的,配合with语句使用。
- find、sort、shuffer方法等可以使用。
- 流操作符号<<和>>符号的使用。
代码
module taa ();
initial begin
$display("time: %t", $time);
end
initial begin
reg a = 'bx;
if($isunknown(a)==1) begin
$display("is un know n x");
end
$display("value x is %d", a);
if (a === 1'bx) begin
$display("is un know n x equal");
end
a = 'bz;
if ($isunknown(a) == 1) begin
$display("is un know n z");
end
if (a === 1'bz) begin
$display("is un know n z equal");
end
end
initial begin
int a[10] = '{10{12}};
a[3:7] = '{default:2};
a[0:1] = '{32, 33};
/* a[5:8] = {default:1}; */
$display("value a %p", a);
end
initial begin
bit [3:0][7:0] a;
a[0] = 8'b1011_0011;
a[1] = 123;
a[3][3] = 1;
$display("pack array a is %h", a);
end
initial begin
bit [3:0] a[5] = '{default:7};
int b[$:5]='{5{1}};
$display("count of a is %0d, %p", $size(a), a);
$display("before: queue of b is %0d, %p", $size(b), b);
b.insert(2, 3);
$display("after: queue of b is %0d, %p", $size(b), b);
$display("type of a is %s", $typename(a));
$display("sum value of a is %d", a.sum() with (item+32'h0));
$display("unique of a is %p", a.unique());
$display("size of a %0d, %p", $size(a), a);
end
initial begin
int a[5] = '{1, 2, 3 ,4, 5};
int ans[$];
a.shuffle();
$display("a is %p", a);
ans = a.find(x) with (x>3);
$display("value ans %p", ans);
ans = a.find_index with(item<3);
$display("value ans %p", ans);
a.sort();
$display("sort a is %p", a);
end
initial begin
bit [15:0] a = 16'ha1a1;
byte b ,c;
a = {<<{a}};
$display("value a is %h", a);
a = {<<byte{a}};
$display("value a is %h", a);
{<<{b, c}} = a;
$display("b, c %h, %h", b , c);
end
endmodule
结果
time: 0
is un know n x
value x is x
is un know n x equal
is un know n z
is un know n z equal
value a '{32, 33, 12, 2, 2, 2, 2, 2, 12, 12}
pack array a is 08007bb3
count of a is 5, '{'h7, 'h7, 'h7, 'h7, 'h7}
before: queue of b is 5, '{1, 1, 1, 1, 1}
after: queue of b is 6, '{1, 1, 3, 1, 1, 1}
type of a is bit[3:0]$[0:4]
sum value of a is 35
unique of a is '{'h7}
size of a 5, '{'h7, 'h7, 'h7, 'h7, 'h7}
a is '{5, 3, 4, 2, 1}
value ans '{5, 4}
value ans '{3, 4}
sort a is '{1, 2, 3, 4, 5}
value a is 8585
value a is 8585
b, c a1, a1
ref和output
由于inout、input、output在赋值过程中如果数据过大,造成堆栈空间的数据复制压力。
sv引入的ref,允许使用引用变量。
笔试错误
PCIe
一种串行接口。
queue的size函数和mailbox的num函数
queue有size函数,没有num函数。mailbox有num函数,没有size函数。
foreach的二维遍历
直接遍历。在取值的时候需要正常调用。
module tbb ();
initial begin
mailbox mbx;
mbx = new();
mbx.put(1);
mbx.put(3);
$display(mbx.num());
end
initial begin
int que[$];
$display("-----------------------------------");
que.push_back(2);
que.push_back(3);
$display(que.size());
end
initial begin
int a[3][4];
$display("-----------------------------------");
a[0] = '{4{2}};
a[1] = '{4{3}};
a[2] = '{4{4}};
foreach (a[, j]) begin
$display(a[2][j]);
end
end
endmodule
输出结果:
2
-----------------------------------
2
-----------------------------------
4
4
4
4
Le vent se lève! . . . il faut tenter de vivre!
Le vent se lève! . . . il faut tenter de vivre!

浙公网安备 33010602011771号