文章目录
复杂电路设计-1
二进制转格雷码&格雷码转二进制
二进制转格雷码
module dual2gray
(input [3:0] dual_data,
output [3:0] gray_data);
assign gray_data[0] = dual_data[0] ^ dual_data[1] ;
assign gray_data[1] = dual_data[1] ^ dual_data[2] ;
assign gray_data[2] = dual_data[2] ^ dual_data[3] ;
assign gray_data[3] = dual_data[3] ;
endmodule
格雷码转二进制
module gray2dual
(input [3:0] gray_data,
output [3:0] dual_data);
assign dual_data[0] = gray_data[0] ^ gray_data[1] ^ gray_data[2] ^ gray_data[3] ;
assign dual_data[1] = gray_data[1] ^ gray_data[2] ^ gray_data[3] ;
assign dual_data[2] = gray_data[2] ^ gray_data[3] ;
assign dual_data[3] = gray_data[3] ;
endmodule
二进制转BCD
算法:加三移位法
二进制满16进一
十进制满10进一
将二进制>=10的数+6,会产生进位,进位分别代表十位的高一位,本位数据和高位数据表示原始值
module bi2BCD(
input [7:0] d_in,
output [11:0] d_out);
reg [3:0] ge,shi,bai;
reg [11:0] d_mid;
integer i;
always@(*) begin
{bai,shi,ge} = 'b0;
for(i = 7;i >= 0;i = i-1)
begin
if( ge > 4 ) begin
{shi,ge} = {shi,ge} + 3;
end
else if (shi > 4 ) begin
{bai,shi} = {bai,shi} + 3;
end
else begin
{bai,shi,ge} = {bai,shi,ge};
end
d_mid = {bai,shi,ge};//最后将d_in[0]输入后结束
{bai,shi,ge} = { d_mid[10:0] , d_in[i] };
end
end
assign d_out = {bai,shi,ge};
endmodule
Testbench
module inst_tb();
reg [7:0] d_in;
wire [11:0] d_out;
initial
begin
d_in = 8'hff;
#10
d_in = 8'h23;
#10
d_in = 8'ha2;
end
inst bi2BCD(.d_in(d_in),.d_out(d_out));
endmodule
秒计数器设计
//系统时钟:10MHz,T为100ps
//基于系统时钟的计数:cont_t(计数范围0-10000000-1),每循环一圈就是1秒。
//秒脉冲:触发器,每看到0就置为1,不是0就置为0,就可以得到一秒一个脉尖冲,称为秒脉冲
//秒计数:对秒脉冲进行计数,看到一个秒脉尖冲加一。(9加1变成0)
module Timer (
input clk;//24MHz
input reset_n
output se
);
reg [31:0] cont_t;
always@(posedge clk)
begin
if(!reset_n) begin
cont_t <= 1;
end
else begin
cont_t <= cont_t + 1;
end
end
assign se = (cont_t==32'b0)? 1'b1:1'b0;
endmodule
线性反馈移位寄存器LFSR
原理参考:https://zhuanlan.zhihu.com/p/366067972
线性反馈移位寄存器(LFSR)的英文全称为:Linear Feedback Shift Register。
LFSR由触发器构成,占用资源相对较少,且可以在FPGA内部以很高的时钟速率运行。
可应用于:
(1)计数器(Counters)
(2)测试码型发生器(Test Pattern Generators)
(3)数据加扰(Data Scrambling)
(4)密码学(Cryptography)
运行LFSR时,由各个触发器生成的模式是伪随机的,这意味着它接近随机。 它不是完全随机的,因为从LFSR模式的任何状态,您都可以预测下一个状态。 有一些重要的移位寄存器属性需要注意:
LFSR模式是伪随机的。
输出模式是确定性的。 可通过XOR门的位置以及当前模式来确定下一个状态。
当抽头使用XOR门时,全0的模式不会出现。 由于0与0异或将始终产生0,因此LFSR将停止运行。
当抽头使用XNOR门时,全1的模式将不会出现。 由于将1与1进行异或运算将始终产生1,因此LFSR将停止运行。
任何LFSR的最大可能迭代次数= 2^Bits-1
LFSR的反馈函数就是简单地对移位寄存器中的某些位进行异或,并将异或的结果填充到LFSR的最左端,如图所示。对于LFSR中每一位的数据,可以参与异或,也可以不参与异或。其中,我们把参与异或的位称为抽头。
//以x8+x4+x3+x2+1为例:参与异或的寄存器为:[7],[3],[2],[1]
module m_LFSR(
input clk,
input rst_n,
output reg [7:0] m_seq
);
wire d;
assign d=m_seq[7]^m_seq[3]^m_seq[2]^m_seq[1];
always@(posedge clk or negedge rst_n)
begin
if (!rst_n)
m_seq<=8'hff;
else
m_seq<={d,m_seq[6:0]};
end
endmodule
4位超前进位加法器
根据全加器进行推导:
输入:a,b,c;输出:c_out,sum
c_out = ab | bc | ac = ab + (a + b) c = ab + (a ^ b) c
sum = a ^ b ^ c;
所以
进位产生函数是:G = ab
进位传输函数是:P = a ^ b
module four_bits_fast_adder(
input [3:0] a,
input [3:0] b,
input c_in,
output [3:0]sum_out,
output c_out);
//wire c1,c2,c3;
assign c1 = ( a[0]&b[0] )|( ( a[0]^b[0] ) &c_in) ;
assign c2 = ( a[1]&b[1] )|( ( a[1]^b[1] ) &c1);
assign c3 = ( a[2]&b[2] )|( ( a[2]^b[2] ) &c2);
assign c_out = ( a[3]&b[3] )|( ( a[3]^b[3] ) &c3);
assign sum_out[0]=(a[0]^b[0])^c_in;
assign sum_out[1]=(a[1]^b[1])^c1;
assign sum_out[2]=(a[2]^b[2])^c2;
assign sum_out[3]=(a[3]^b[3])^c3;
endmodule
加法器树乘法器
module mul_addtree(
input [3:0] mul_a,mul_b,
output [7:0] mul_out);
wire [3:0] stored0;
wire [5:0] stored1;
wire [6:0] stored2;
wire [7:0] stored3;
assign stored0 = {4{mul_a[0]}} & mul_b;
assign stored1 = (mul_a[1])? ( mul_b )<<1 : 'b0;//判断存不存在数据丢失情况
assign stored2 = (mul_a[2])? ( mul_b )<<2 : 'b0;
assign stored3 = (mul_a[3])? ( mul_b )<<3 : 'b0;
assign mul_out = stored0 + stored1 +stored2 +stored3;
endmodule
流水线结构
流水线就是在每一级组合逻辑中间加入触发器/寄存器组来暂存上一级产生的值,可提高相关电路的处理速度。
module mul_addtree_2_stage(
input clk,rst_n,
input [3:0] mul_a,mul_b,
output [7:0] mul_out);
wire [3:0] stored0;
wire [5:0] stored1;
wire [6:0] stored2;
wire [7:0] stored3;
//流水线,触发器组暂存中间值
wire [7:0] add_tmp_1,add_tmp_2,mul_tmp;
reg [7:0] add_tmp_1_reg,add_tmp_2_reg,mul_tmp_reg;
//combinatorial logic
assign stored0 = {4{mul_a[0]}} & mul_b;
assign stored1 = (mul_a[1])? ( {4{mul_a[1]}} & mul_b )<<1 : 'b0;
assign stored2 = (mul_a[2])? ( {4{mul_a[2]}} & mul_b )<<2 : 'b0;
assign stored3 = (mul_a[3])? ( {4{mul_a[3]}} & mul_b )<<3 : 'b0;
assgin add_tmp_1 = stored0 + stored1;
assign add_tmp_2 = stored2 + stored3;
assign mul_tmp = add_tmp_1 + add_tmp_2;
//sequential logic
always@(posedge clk)
begin
if (!rst_n)
add_tmp_1_reg <= 'b0;
add_tmp_2_reg <= 'b0;
mul_tmp_reg <= 'b0;
else
add_tmp_1_reg <= add_tmp_1;
add_tmp_2_reg <= add_tmp_2;
mul_tmp_reg <= mul_tmp;
end
assign mul_out = mul_tmp_reg;
endmodule
向量点积乘法器
采用模块层次化设计方法,设计4维向量点积乘法器,其中向量a = (a1 , a2 , a3 , a4);b = (b1 , b2 , b3 , b4)。
点积乘法规则:a · b = a1b1 + a2b2 + a3b3 + a4b4
模块化加法器和加法树乘法器
module vector(
input [3:0] a1,a2,a3,a4,b1,b2,b3,b4,
output [9:0] out);
wire [7:0] out1,out2,out3,out4;
wire c_mid;
//实例化加法器树乘法器
mul_addtree u1(.mul_a(a1),.mul_b(b1),.mul_out(out1));
mul_addtree u2(.mul_a(a2),.mul_b(b2),.mul_out(out2));
mul_addtree u3(.mul_a(a3),.mul_b(b3),.mul_out(out3));
mul_addtree u4(.mul_a(a4),.mul_b(b4),.mul_out(out4));
assign out=out1+out2+out3+out4;
endmodule
Wallace树型乘法器
module wallace_tree (
input [3:0] a,b,
output [7:0] dout
);
wire [15:0] tem_and;
assign tem_and = { a[3],a[2],a[1],a[0],
a[3],a[2],a[1],a[0],
a[3],a[2],a[1],a[0],
a[3],a[2],a[1],a[0],} &
{b[0],b[0],b[0],b[0],
b[1],b[1],b[1],b[1],
b[2],b[2],b[2],b[2],
b[3],b[3],b[3],b[3],
};
//第一级产生的sum1_x和cout1_x,2个半加器
// * * * *
// * * * *
// * + + *
// * * + +
wire sum1_1,sum1_2;
wire cout1_1,cout1_2;
half_adder u1_1(.a(tem_and[10]),.b(tem_and[15]),.sum(sum1_1),.c_out(cout1_1));
half_adder u1_2(.a(tem_and[9]), .b(tem_and[14]),.sum(sum1_2),.c_out(cout1_2));
//第二级产生的sum2_x和cout2_x,3个全加器,1个半加器
// * * * *
// * * * *
// * s1 s2 *
// * * c2
// c1
wire sum2_1,sum2_2,sum2_3,sum2_4;
wire cout2_1,cout2_2,cout2_3,cout2_4;
full_adder u2_1(.a(tem_and[8]),.b(tem_and[13]),.c(cout1_1), .sum(sum2_1),.c_out(cout2_1));
full_adder u2_2(.a(tem_and[5]),.b(sum1_1), .c(cout1_2), .sum(sum2_2),.c_out(cout2_2));
full_adder u2_3(.a(tem_and[0]),.b(tem_and[5]), .c(sum1_2), .sum(sum2_3),.c_out(cout2_3));
half_adder u2_4(.a(tem_and[6]),.b(tem_and[11]),.sum(sum2_4), .c_out(cout2_4));
//第三级可使用超前进位加法器,这里直接相加
// s3 * * *
// s2 c4 s4 *
// s1 c3
// * c2
// c1
wire [6:0] tem_fast_add;
assign tem_fast_add = {tem_and[12],sum2_1, sum2_2, sum2_3, tem_and[1],tem_and[2]} + {
cout2_1, cout2_2,cout2_3,cout2_4,sum2_4, tem_and[7]};
assign dout={tem_fast_add,tem[3]};
endmodule
//全加器
module full_adder(
input a,b,c,
output sum,c_out);
assign {c_out,sum} = a+b+c;
endmodule
//半加器
module half_adder(
input a,b,
output c_out,sum);
assign c_out = a&b;
assign sum = a|b;
endmodule
复数乘法器
//调用Wallace树乘法器
module complex(
input [3:0] a,b,c,d;
output [8:0] out_real,out_im);
wire [7:0] ad,ac,bc,bd;
wallace u1(.x(a),.y(d),.out(ad);
wallace u2(.x(a),.y(c),.out(ac);
wallace u3(.x(d),.y(b),.out(bd);
wallace u4(.x(b),.y(c),.out(bc);
assign out_real = ac - bd;
assign out_im = ad + bc;
endmodule
Booth乘法器
module dut (
input [7:0] a,
input [7:0] b,
output [15:0] out_mul
);
//暂存y5+y6-2*y7
//y3+y4-2*y5
//y1+y2-2*y3
//y-1+y0-2*y1计算相减会引入补码,增大复杂度
//8位的Booth2位乘:Y=(y5+y6-2*y7)*(2**6) + (y3+y4-2*y5)*(2**4) + (y1+y2-2*y3)*(2**2) + (y-1+y0-2*y1)*(2**0)
//直接判断相减的 所有 结果:
//000——0,001——-2,010——1,011——-1
//100——1,101——-1,110——2,111——0
// {a[5],a[6],a[7]}==3'b000 ?
//变成补码,则此时默认a,b以原码的形式
wire [7:0] a_com,b_com;
//assign a_com = (a[7])? {a[7],(~a[6:0]+1'b1)} : a;
//assign b_com = (b[7])? {b[7],(~b[6:0]+1'b1)} : b;
assign a_com = a, b_com = b;//计算机以补码的形式存储数据
//8位数的Booth二位乘分别暂存于下列值(左移0,2,4,6位)
reg [15:0] tem_0,tem_2,tem_4, tem_6;
reg [15:0] mid_0,mid_2,mid_4,mid_6;//存储中间值,若为负,取其补码
//always @(*) begin里面是reg!!!!!!!!!!!!!!!!
//*(2**6)
always @(*) begin
case ( {a[5],a[6],a[7]} )
3'b000,3'b111 : //0
begin
tem_6='b0;
end
3'b010,3'b100 : //1
begin
tem_6= {{2{b[7]}},b_com,6'b0};
end
3'b101,3'b011 : //-1
begin
mid_6= {{2{b[7]}},b_com,6'b0};
tem_6 =~mid_6+1;
end
3'b110 : //2
begin
tem_6= {b[7],b_com,7'b0};
end
3'b001 : //-2
begin
mid_6 = {b[7],b_com,7'b0};
tem_6= ~mid_6 + 1;
end
endcase
end
//*(2**4)
always @(*) begin
case ( {a[3],a[4],a[5]} )
3'b000,3'b111 : //0
begin
tem_4 ='b0;
end
3'b010,3'b100 : //1
begin
tem_4 = {{4{b[7]}},b_com,4'b0};
end
3'b101,3'b011 : //-1
begin
mid_4 = {{4{b[7]}},b_com,4'b0};
tem_4 = ~mid_4 + 1;
end
3'b110 : //2
begin
tem_4 = {{3{b[7]}},b_com,5'b0};
end
3'b001 : //-2
begin
mid_4 = {{3{b[7]}},b_com,5'b0};
tem_4 = ~mid_4 + 1;
end
endcase
end
//*(2**2)
always @(*) begin
case ( {a[1],a[2],a[3]} )
3'b000,3'b111 : //0
begin
tem_2='b0;
end
3'b010,3'b100 : //1
begin
tem_2= {{6{b[7]}},b_com,2'b0};
end
3'b101,3'b011 : //-1
begin
mid_2 = {{6{b[7]}},b_com,2'b0};
tem_2= ~mid_2 + 1;
end
3'b110 : //2
begin
tem_2= {{5{b[7]}},b_com,3'b0};
end
3'b001 : //-2
begin
mid_2 = {{5{b[7]}},b_com,3'b0};
tem_2 = ~mid_2 + 1;
end
endcase
end
//*(2**0)
always @(*) begin
case ( {1'b0,a[0],a[1]} ) //y(x-1)+y(x)-2*y(x+1)
3'b000,3'b111 : //0
begin
tem_0='b0;
end
3'b010,3'b100 : //1
begin
tem_0= {{8{b[7]}},b_com};
end
3'b101,3'b011 : //-1
begin
mid_0 = {{8{b[7]}},b_com};
tem_0 = ~mid_0 + 1;
end
3'b110 : //2
begin
tem_0= {{7{b[7]}},b_com,1'b0};
end
3'b001 : //-2
begin
mid_0 = {{7{b[7]}},b_com,1'b0};
tem_0 = ~mid_0 + 1;
end
endcase
end
assign out_mul = tem_0 + tem_2 + tem_4 + tem_6;//可采用超前进位加法器进一步增速
endmodule
Testbench
`timescale 1ns / 1ns
//
// Company:
// Engineer: CLL
//
// Create Date: 2020/03/04 16:42:17
// Design Name:
// Module Name: dsram_tsb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module dut_tb(
);
reg [7:0] a ;
reg [7:0] b ;
wire [15:0] out_mul ;
initial begin
#1
a = -8'd6;
b = -8'd7;
#50
a = 8'd6;
b = -8'd7;
#50
a = -8'd6;
b = 8'd7;
#50
a = -8'd15;
b = -8'd10;
#50
a = -8'd10;
b = -8'd10;
#50
a = -8'd15;
b = -8'd200;
#50
a = 8'd11;
b = -8'd11;
#50
a = -8'd15;
b = 8'd10;
#50
a = 8'd12;
b = 8'd12;
end
dut inst(
.a (a ),
.b (b ),
.out_mul (out_mul )
);
endmodule
片内存储器设计
单端口RAM
例:用Verilog HDL设计深度为8,位宽为8的单端口RAM(单口RAM,只有一套地址总线,读操作和写操作是分开的)1:读 0:写
当片选信号无效时,输出8’bzzzz_zzzz
module ram_single (
input clk,
input [2:0] addm, //address signal
input cs_n, //chip select signal
input we_n, // 0:write 1:read
input [7:0] din,
output reg [7:0] dout,//sequential not forget reg
);
reg [7:0] mem1 [7:0];
always @(posedge clk)
begin
if ( we_n & cs_n)
dout <= mem1[addm];
else if (!we_n & cs_n)
mem1 [addm] <= din;
else
dout <= 8'bzzzz_zzzz;
end
endmodule
双端口RAM
例:用Verilog HDL设计深度为8,位宽为8的双端口RAM。
双口RAM具有两套地址总线,一套用于读数据,另一套用于写数据。二者可以分别独立操作。
module ram_dual (
input clk1,
input [2:0] add_in, //address signal
input [7:0] din,
input write, // 0:write 1:read
input clk2,
input read, //chip select signal
input [2:0] add_out,
output reg [7:0] dout,//sequential not forget reg
);
reg [7:0] mem1 [7:0];
always @(posedge clk1)
begin
if ( write )
mem1 [add_in] <= din;
else
mem1 [add_in] <= mem1 [add_in];
end
always @(posedge clk2 )
begin
if ( read )
dout <= mem1 [add_out];
else
dout <= mem1 [add_out];
end
endmodule
ROM
(2)ROM的Verilog HDL描述
ROM即只读存储器,是一种只能读出事先存储的数据的存储器,其特性是存入数据无法改变,也就是说这种存储器只能读不能写。由于ROM在断电之后数据不会丢失,所以通常用在不需经常变更资料的电子或电脑系统中,资料并不会因为电源关闭而消失。
采用initial初始化ROM中的值,并不修改
module rom (
input clk,cs_n,
input [2:0] addm,
output reg [7:0] dout,
);
reg [7:0] rom [7:0];//定义一个rom
//数据存储为固定值
initial
begin
rom[0] = 8'b0000_0000;
rom[1] = 8'b0000_0010;
rom[3] = 8'b0000_0011;
rom[4] = 8'b0000_0100;
rom[5] = 8'b0000_0101;
rom[6] = 8'b0000_0110;
rom[7] = 8'b0000_0111;
rom[8] = 8'b0000_1000;
end
always @(posedge clk)
begin
if ( !cs_n )
dout <= rom[addm];
else
dout <= 8'bzzzz_zzzz;
end
endmodule
同步FIFO
FIFO (First In First Out)是一种先进先出的数据缓存器,通常用于接口电路
的数据缓存。与普通存储器的区别是没有外部读写地址线,可以使用两个时
钟分别进行写和读操作。FIFO只能顺序写入数据和顺序读出数据,其数据地
址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读
取或写入某个指定的地址。
FIFO由存储器块和对数据进出FIFO的通道进行管理的控制器构成,每次只对
一个寄存器提供存取操作,而不是对整个寄存器阵列进行。FIFO有两个地址
指针,一个用于将数据写入下一个可用的存储单元,一个用于读取下一个未
读存储单元的操作。读写数据必须一次进行。
同步FIFO就是读写时钟域均为同一个时钟的FIFO。
clk:读写时钟
rst_n:同步复位信号
wr_en:写使能信号
rd_en:读使能信号
din:输入数据信号
dout:读出数据信号
full:满信号
empty:空信号
整体模块包含:写模块,读模块,更新指针,FIFO计数模块
`timescale 1ns / 1ns
//
// Company:
// Engineer:
//
// Create Date: 2022/02/24 18:47:02
// Design Name:
// Module Name: inst
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module inst
#(parameter DATA_SIZE = 8,
parameter ADDR_SIZE = 8
)(
input clk, //
input rst_n, //同步复位
input wr_en, //写使能、读使能
input rd_en,
input [DATA_SIZE-1:0] din, //输入输出数据
output reg [DATA_SIZE-1:0] dout,
output full, //输出空满状态
output empty);
reg [DATA_SIZE-1:0] mem1 [0:ADDR_SIZE-1]; //reg [wordsize : 0] array_name [0 : arraysize];
//定义读写指针
reg [2:0] wr_ptr;
reg [2:0] re_ptr;
//定义计数器,记录存入数据个数
reg [3:0] fifo_ctr;
assign full = (fifo_ctr==4'b1000)?1'b1:1'b0;
assign empty = (fifo_ctr==4'b0)? 1'b1:1'b0;
//读操作read
always @( posedge clk ) begin
if (!empty&rd_en) //读有效,FIFO非空
dout <= mem1[re_ptr];
else if (empty & rd_en & wr_en) //空,但读写同时有效
dout <= din;
else
dout <= 'b0;
end
//写操作write
always @( posedge clk ) begin
if (!full & wr_en)
mem1[wr_ptr] <= din;
else if (wr_en & rd_en)
//读写同时有效,先进先出,数据总数不变,相当于数据出去并补足一位
mem1[wr_ptr] <= din;
end
//清空FIFO,FIFO复位之后empty信号默认为高,
//在工作中需要一次性清空FIFO中的数据时,
//要对FIFO的复位信号产生一个上升沿即可实现FIFO的清空
//指针生成pointer
always @( posedge clk ) begin
if (!rst_n) begin
re_ptr <= 3'b0; //从低地址开始读
wr_ptr <= 3'b0; //从低地址开始读
end
else begin
//注意读写同时有效的情况,指针发生改变,但是数据总量不变
re_ptr <= ((!empty & rd_en) || (wr_en & rd_en))? re_ptr+3'b1 : re_ptr;
wr_ptr <= ((!full & wr_en) || (wr_en & rd_en))? wr_ptr+3'b1 : wr_ptr;
//写指针满后自动指向[0]
end
end
//计数器counter
always @( posedge clk ) begin
if (!rst_n)
fifo_ctr <= 'b0;
else begin
case ({rd_en , wr_en})
2'b00: fifo_ctr <= fifo_ctr;
2'b01: fifo_ctr <= (!full) ? fifo_ctr+1 : fifo_ctr;
2'b10: fifo_ctr <= (!empty)? fifo_ctr-1 : fifo_ctr;
2'b11: fifo_ctr <= fifo_ctr;
default: fifo_ctr <= fifo_ctr;
endcase
end
end
endmodule
Testbench
来源于
`timescale 1ns / 1ps
module TB_async_fifo;
parameter DATA_SIZE = 8;
parameter ADDR_SIZE = 8;
parameter CLK_PERIOD = 10;
integer i = 3;
reg clk;
reg rst_n;
reg w_en;
reg r_en;
reg [DATA_SIZE-1:0] wdata;
wire [DATA_SIZE-1:0] rdata;
wire wfull;
wire rempty;
initial begin
clk = 0;
end
always#(CLK_PERIOD/2) clk = ~clk;
initial begin;
rst_n = 1'b0;
#15;
rst_n = 1'b1;
end
// always@(rst_n or wfull) begin
// if(rst_n==1'b0)
// w_en = 1'b0;
// else if(!wfull)
// w_en = 1'b1;
// else
// w_en = 1'b0;
// end
always@(posedge clk or negedge rst_n) begin
if(rst_n==1'b0)
w_en = 1'b0;
else if(!wfull)
w_en = 1'b1;
else
w_en = 1'b0;
end
always@(rst_n or rempty) begin
if(rst_n==1'b0)
r_en =1'b0;
else if(!rempty)
r_en = 1'b0;
else
r_en = 1'b0;
end
//always@(posedge clk or negedge rst_n) begin
// if(rst_n==1'b0)
// r_en =1'b0;
// else if(!rempty)
// r_en = 1'b1;
// else
// r_en = 1'b0;
//end
always@(posedge clk or negedge rst_n) begin
if(rst_n==1'b0)
i <= 3;
else if(!wfull)
i <= i+1;
else
i <= i;
end
always@(*) begin
if(rst_n==1'b0)
wdata = 0;
else if(!wfull&&w_en==1)
wdata = i;
else
wdata <= 0;
end
inst#(
.DATA_SIZE(DATA_SIZE),
.ADDR_SIZE(ADDR_SIZE)
)
uut(
.clk(clk),
.rst_n(rst_n),
.wr_en(w_en),
.rd_en(r_en),
.din(wdata),
.dout(rdata),
.full(wfull),
.empty(rempty)
);
endmodule
参考