(原创)system verilog——同步fifo
本例代码都已给出,可以在MODELSIM6.3F中直接运行,大家通过下面仿真波形可以看到,有六个断言成功,0个断言失败,
成功的断言分别是:三个写入数据时,status的前后状态变化的断言;三个读出数据时,status的前后状态变化的断言。
代码如下:
Code
1`timescale 1ns/10ps
2module syn_fifo(clk,
3 rst,
4 wr_cs,
5 wr_en,
6 din,
7 rd_cs,
8 rd_en,
9 dout,
10 empty,
11 full
12);
13parameter DATA_WIDTH=8;
14parameter ADDR_WIDTH=8;
15parameter DEPT_WIDTH=(1<<ADDR_WIDTH);
16parameter fifo_sva=1'b1;
17input clk;
18input rst;
19input wr_cs;
20input rd_cs;
21input [DATA_WIDTH-1:0] din;
22input rd_en;
23input wr_en;
24output [DATA_WIDTH-1:0] dout;
25output empty;
26output full;
27
28logic [ADDR_WIDTH-1:0] wptr;
29logic [ADDR_WIDTH-1:0] rptr;
30logic [ADDR_WIDTH-1:0] status;
31assign empty=(status==0);
32assign full=(status==DEPT_WIDTH);
33// write data into fifo
34always@(posedge clk or posedge rst)
35begin
36 if(rst)begin
37 wptr=0;
38 end
39 else if(wr_en&&wr_cs&&!full)begin
40 wptr=wptr+1;
41 end
42end
43//read data from fifo
44always@(posedge clk or posedge rst)
45begin
46 if(rst)begin
47 rptr=0;
48 end
49 else if(rd_en&&rd_cs&&!empty)begin
50 rptr=rptr+1;
51 end
52end
53//count fifo status
54always@(posedge clk or posedge rst)
55begin
56 if(rst)begin
57 status=0;
58 end
59 else if((wr_en&&wr_cs)&&!(rd_en&&rd_cs)&&!full)begin
60 status=status+1;
61 end
62 else if(!(wr_en&&wr_cs)&&(rd_en&&rd_cs)&&!empty)begin
63 status=status-1;
64 end
65 else begin
66 status=status;
67 end
68end
69asyn_dp_ram#(DATA_WIDTH,ADDR_WIDTH,DEPT_WIDTH)
70 u(.din(din),
71 .wptr(wptr),
72 .wr_en(wr_en),
73 .wr_cs(wr_cs),
74 .dout(dout),
75 .rptr(rptr),
76 .rd_en(rd_en),
77 .rd_cs(rd_cs)
78 );
79 //sva property description
80property p_write_not_read;
81 @(posedge clk)
82 (wr_cs&&wr_en&&!rd_cs&&!rd_en&&!full)|=>(status==$past(status)+1);
83endproperty
84property p_read_not_write;
85 @(posedge clk)
86 (!wr_cs&&!wr_en&&rd_cs&&rd_en&&!empty)|=>(status==$past(status)-1);
87endproperty
88property p_write_and_read;
89 @(posedge clk)
90 (wr_cs&&wr_en&&rd_cs&&rd_en)|=>(status==$past(status));
91endproperty
92
93//sva check
94always@(posedge clk)
95if(fifo_sva)
96begin
97a_write_not_read:assert property(p_write_not_read)
98 else $display("write error at %d !",$time);
99a_read_not_write:assert property(p_read_not_write)
100 else $display("read error at %d !",$time);
101a_write_and_read:assert property(p_write_and_read)
102 else $display("write and read error at %d !",$time);
103
104c_write_not_read:cover property(p_write_not_read);
105c_read_not_write:cover property(p_read_not_write);
106c_write_and_read:cover property(p_write_and_read);
107end
108endmodule
109
110
111
112`timescale 1ns/10ps
113module asyn_dp_ram(din,wptr,wr_en,wr_cs,dout,rptr,rd_en,rd_cs);
114parameter DATA_WIDTH=8;
115parameter ADDR_WIDTH=8;
116parameter DEPT_WIDTH=(1<<ADDR_WIDTH);
117input [DATA_WIDTH-1:0] din;
118input [ADDR_WIDTH-1:0] wptr;
119input [ADDR_WIDTH-1:0] rptr;
120input wr_en;
121input wr_cs;
122input rd_en;
123input rd_cs;
124output [DATA_WIDTH-1:0] dout;
125
126logic [DATA_WIDTH-1:0] dout;
127logic [DATA_WIDTH-1:0] mem [DEPT_WIDTH-1:0];
128//write data port
129always@(din or wptr or wr_en or wr_cs)
130begin
131if(wr_en&&wr_cs)
132mem[wptr]=din;
133end
134//read data port
135always@(rptr or rd_en or rd_cs)
136begin
137if(rd_en&&rd_cs)
138dout=mem[rptr];
139end
140
141endmodule
142
143
144
145
146`timescale 1ns/10ps
147module syn_fifo_testbench;
148logic clk;
149logic rst;
150logic wr_cs;
151logic rd_cs;
152logic [7:0] din;
153logic rd_en;
154logic wr_en;
155wire [7:0] dout;
156wire empty;
157wire full;
158syn_fifo #(8,4,256,1)
159 u1(.clk(clk),
160 .rst(rst),
161 .wr_cs(wr_cs),
162 .wr_en(wr_en),
163 .din(din),
164 .rd_cs(rd_cs),
165 .rd_en(rd_en),
166 .dout(dout),
167 .empty(empty),
168 .full(full)
169);
170parameter p=10;
171initial
172begin
173wr_cs=0;
174wr_en=0;
175rd_cs=0;
176rd_en=0;
177clk=0;
178rst=1;
179#p rst=0;
180#p wr_cs=1;
181 wr_en=1;
182 din=8'b10101010;
183#p din=8'b11001100;
184#p din=8'b11111111;
185#p wr_cs=0;
186#p wr_en=0;
187#p rd_cs=1;
188#p rd_en=1;
189#p ;
190#p ;
191#p rd_cs=0;
192#p rd_en=0;
193#1000 $finish;
194end
195initial
196begin
197$monitor("the din is %b ,out is %b at %d",din,dout,$time);
198//$monitor("the dout is %b at %d",dout,$time);
199end
200always #5 clk=~clk;
201endmodule
202
203
1`timescale 1ns/10ps
2module syn_fifo(clk,
3 rst,
4 wr_cs,
5 wr_en,
6 din,
7 rd_cs,
8 rd_en,
9 dout,
10 empty,
11 full
12);
13parameter DATA_WIDTH=8;
14parameter ADDR_WIDTH=8;
15parameter DEPT_WIDTH=(1<<ADDR_WIDTH);
16parameter fifo_sva=1'b1;
17input clk;
18input rst;
19input wr_cs;
20input rd_cs;
21input [DATA_WIDTH-1:0] din;
22input rd_en;
23input wr_en;
24output [DATA_WIDTH-1:0] dout;
25output empty;
26output full;
27
28logic [ADDR_WIDTH-1:0] wptr;
29logic [ADDR_WIDTH-1:0] rptr;
30logic [ADDR_WIDTH-1:0] status;
31assign empty=(status==0);
32assign full=(status==DEPT_WIDTH);
33// write data into fifo
34always@(posedge clk or posedge rst)
35begin
36 if(rst)begin
37 wptr=0;
38 end
39 else if(wr_en&&wr_cs&&!full)begin
40 wptr=wptr+1;
41 end
42end
43//read data from fifo
44always@(posedge clk or posedge rst)
45begin
46 if(rst)begin
47 rptr=0;
48 end
49 else if(rd_en&&rd_cs&&!empty)begin
50 rptr=rptr+1;
51 end
52end
53//count fifo status
54always@(posedge clk or posedge rst)
55begin
56 if(rst)begin
57 status=0;
58 end
59 else if((wr_en&&wr_cs)&&!(rd_en&&rd_cs)&&!full)begin
60 status=status+1;
61 end
62 else if(!(wr_en&&wr_cs)&&(rd_en&&rd_cs)&&!empty)begin
63 status=status-1;
64 end
65 else begin
66 status=status;
67 end
68end
69asyn_dp_ram#(DATA_WIDTH,ADDR_WIDTH,DEPT_WIDTH)
70 u(.din(din),
71 .wptr(wptr),
72 .wr_en(wr_en),
73 .wr_cs(wr_cs),
74 .dout(dout),
75 .rptr(rptr),
76 .rd_en(rd_en),
77 .rd_cs(rd_cs)
78 );
79 //sva property description
80property p_write_not_read;
81 @(posedge clk)
82 (wr_cs&&wr_en&&!rd_cs&&!rd_en&&!full)|=>(status==$past(status)+1);
83endproperty
84property p_read_not_write;
85 @(posedge clk)
86 (!wr_cs&&!wr_en&&rd_cs&&rd_en&&!empty)|=>(status==$past(status)-1);
87endproperty
88property p_write_and_read;
89 @(posedge clk)
90 (wr_cs&&wr_en&&rd_cs&&rd_en)|=>(status==$past(status));
91endproperty
92
93//sva check
94always@(posedge clk)
95if(fifo_sva)
96begin
97a_write_not_read:assert property(p_write_not_read)
98 else $display("write error at %d !",$time);
99a_read_not_write:assert property(p_read_not_write)
100 else $display("read error at %d !",$time);
101a_write_and_read:assert property(p_write_and_read)
102 else $display("write and read error at %d !",$time);
103
104c_write_not_read:cover property(p_write_not_read);
105c_read_not_write:cover property(p_read_not_write);
106c_write_and_read:cover property(p_write_and_read);
107end
108endmodule
109
110
111
112`timescale 1ns/10ps
113module asyn_dp_ram(din,wptr,wr_en,wr_cs,dout,rptr,rd_en,rd_cs);
114parameter DATA_WIDTH=8;
115parameter ADDR_WIDTH=8;
116parameter DEPT_WIDTH=(1<<ADDR_WIDTH);
117input [DATA_WIDTH-1:0] din;
118input [ADDR_WIDTH-1:0] wptr;
119input [ADDR_WIDTH-1:0] rptr;
120input wr_en;
121input wr_cs;
122input rd_en;
123input rd_cs;
124output [DATA_WIDTH-1:0] dout;
125
126logic [DATA_WIDTH-1:0] dout;
127logic [DATA_WIDTH-1:0] mem [DEPT_WIDTH-1:0];
128//write data port
129always@(din or wptr or wr_en or wr_cs)
130begin
131if(wr_en&&wr_cs)
132mem[wptr]=din;
133end
134//read data port
135always@(rptr or rd_en or rd_cs)
136begin
137if(rd_en&&rd_cs)
138dout=mem[rptr];
139end
140
141endmodule
142
143
144
145
146`timescale 1ns/10ps
147module syn_fifo_testbench;
148logic clk;
149logic rst;
150logic wr_cs;
151logic rd_cs;
152logic [7:0] din;
153logic rd_en;
154logic wr_en;
155wire [7:0] dout;
156wire empty;
157wire full;
158syn_fifo #(8,4,256,1)
159 u1(.clk(clk),
160 .rst(rst),
161 .wr_cs(wr_cs),
162 .wr_en(wr_en),
163 .din(din),
164 .rd_cs(rd_cs),
165 .rd_en(rd_en),
166 .dout(dout),
167 .empty(empty),
168 .full(full)
169);
170parameter p=10;
171initial
172begin
173wr_cs=0;
174wr_en=0;
175rd_cs=0;
176rd_en=0;
177clk=0;
178rst=1;
179#p rst=0;
180#p wr_cs=1;
181 wr_en=1;
182 din=8'b10101010;
183#p din=8'b11001100;
184#p din=8'b11111111;
185#p wr_cs=0;
186#p wr_en=0;
187#p rd_cs=1;
188#p rd_en=1;
189#p ;
190#p ;
191#p rd_cs=0;
192#p rd_en=0;
193#1000 $finish;
194end
195initial
196begin
197$monitor("the din is %b ,out is %b at %d",din,dout,$time);
198//$monitor("the dout is %b at %d",dout,$time);
199end
200always #5 clk=~clk;
201endmodule
202
203
完整代码: