几个经典的简单例程
module MUX41a(a,b,c,d,s1,s0,y);
input a,b,c,d;
input s0,s1;
output y;
reg y;//变量有两种,寄存器类型(reg)和线型(wire),没有特意定义的,一般默认为wire类型
//只能对寄存器类型端口赋值
always@(a,b ,c ,d ,s1 ,s0)//必须列入所有输入端口
begin : MUX41
case({s1,s0})
2'b00: y<=a;
2'b01: y<=b;
2'b10: y<=c;
2'b11: y<=d;
default: y<=a;
endcase
end
//case是一种全等比较,必须每一位都相同
//casez语句用来处理不考虑高阻态z的比较过程
//casex语句用来处理不考虑高阻值Z和不定值x的情况
module DFF1 (CLK,D,Q);
output Q;
input CLK,D;
reg Q;
always@ (posedge CLK)
Q<=D;
endmodule
/*时序模块的简单识别,
1、always的敏感信号列表含有posedge或者negedge
2、always语句中有不完整的条件语句,例如if(CLK) Q
*/
//一般,组合电路用阻塞式赋值,时序电路用非阻塞式赋值
/*含异步清零和时钟同步使能的D触发器*/
module DFF2 (CLK,D,Q,RST,EN);//同步,依赖时钟;异步,不依赖时钟
output Q;
input CLK,D,RST,EN;
always@(posedge CLK or negedge RST)
//异步清零,该复位信号出现在always中,与时钟在一起,说明不依赖时钟,为异步
begin
if(!RST) Q<=0;
else if(EN) Q<=D;
end
endmodule
module CNT10 (CLK,RST,EN,LOAD,COUT,DOUT,DATA);
input CLK,EN,RST,LOAD;
input [3:0] DATA;//4位并行加载数据
output [3:0] DOUT;//计数数据输出
output COUT;
reg [3:0] Q1; reg COUT;
assign DOUT=Q1;//将内部寄存器的计数结果输出至DOUT
always@(posedge CLK or negedge RST) begin
if(!RST) Q1<=0;//异步清零
//RST下降沿时,清零,
//之后,若RST一直低电平,则一直清零状态
//当CLK上升沿,并且RST=1,EN=1时,看LOAD的值
//LOAD=0时,置数,LOAD=1时,累加1
else if(EN) begin //同步使能EN=1,此时允许加载或计数
if(!LOAD) Q1<=DATA;//当LOAD=0,向内部寄存器加载数据
else if(Q1<9) Q1<=Q1+1;//当Q1小于9时,允许累加,此时为十进制计数器
else Q1<=4'b0000; end
end
always@ (Q1)//组合逻辑电路
if(Q1==4'h9) COUT=1'b1; //当Q1=1001时,COUT输出进位标志1
else COUT=1'b0; //否则,输出进位标志0
endmodule
module SHFT2(CLK,C0,MD,D,QB,CN);
output CN;//进位输出
output [7:0] QB;//移位数据输出
input [7:0] D;//待加载移位的数据输入
input [2:0] MD;//移位模式控制字
input CLK,C0;//时钟和进位输入
reg [7:0] REG; reg CY;
always@(posedge CLK) begin
case(MD)
1:begin REG[0]<=C0;REG[7:1]<=REG[6:0]; CY<=REG[7];end //带进位循环左移
2:begin REG[0]<=REG[7]; REG[7:1]<=REG[6:0]; end //自循环左移
3:begin REG[7]<=REG[0]; REG[6:0]<=REG[7:1]; end //自循环右移
4:begin REG[7]<=C0; REG[6:0]<=REG[7:1]; CY=REG[0]; end //带进位循环右移
5:begin REG<=D; end //加载待移数
default:begin REG<=REG;CY<=CY;end //过程结束
endcase end
assign QB=REG;//移位数据并行输出
assign CN=CY;//左移高位输出
endmodule
module sc_fifo(
input clk,rst,
input [7:0] din,
input wr,
output full,
output reg [7:0] dout,
input rd,
output empty
);
//1,需要一个buff双口存储器做存储载体,当地址有n位,就有2^N个存储单元,标号从0到(2^N-1)。三位地址存储地址就是从0到7。
reg [7:0] buff[0:7];
//2,需要wr_ptr指针,与地址位数相同,指向下个可以写的地址。
reg [2:0] wr_ptr;
//3,需要rd_ptr指针,与地址位数相同,指向下个可以读的地址。
reg [2:0] rd_ptr;
//4,需要fifo_cntr计数器,比地址位数多一位,指示当前可读的数据个数。
reg [3:0] fifo_cntr;
//5,full和empty由fifo_cntr生成。
assign full=fifo_cntr==8;
assign empty=fifo_cntr==0;
//6,区别读写操作是否有效。
wire valid_rd=~empty &rd;
wire valid_wr=~full≀
//7,实现以上功能
always@(posedge clk) if(rst) wr_ptr<=0;else if (valid_wr) wr_ptr<=wr_ptr+1;
always@(posedge clk) if(rst) rd_ptr<=0;else if (valid_rd) rd_ptr<=rd_ptr+1;
always@(posedge clk) if(rst) fifo_cntr<=0;else
if ((valid_rd==0)&&(valid_wr==1)) fifo_cntr<=fifo_cntr+1;
else if ((valid_rd==1)&&(valid_wr==0)) fifo_cntr<=fifo_cntr-1;
/*用case语句写
always@(posedge clk)
casex ({rst,valid_wr,valid_rd})
3'b1xx : fifo_cntr<=0;
3'b010 : fifo_cntr<=fifo_cntr+1;
3'b001 : fifo_cntr<=fifo_cntr-1;
3'b011 ,3'b000 :fifo_cntr<=fifo_cntr ;
endcase */
always@(posedge clk) if(valid_wr) buff[wr_ptr]<=din;
always@(posedge clk) if(valid_rd) dout<=buff[rd_ptr];
endmodule