1.二进制与格雷码转换
转格雷码:
module binary2grey #(
parameter N = 4
)(
input [N-1: 0] binary ,
output wire [N-1: 0] grey
);
assign grey =(binary>>1)^binary;
endmodule
转二进制:
module grey2binary #(
parameter N = 4
)(
input [N-1: 0] grey ,
output wire [N-1: 0] binary
);
assign binary[N-1] = grey[N-1]; endmodule
generate
genvar i;
for(i=0;i<N-1;i=i+1) begin:b2g
assign binary[i] = grey[i]^binary[i+1];
end
endgenerate
endmodule
2.下降沿
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
d0 <= 1'b0;
d1 <= 1'b0;
end
else begin
d0 <= gate;
d1 <= d0;
end
end
assign sign=d1&(~d0);
3.8bit 全加器
module adder_8(s, cout, a, b, cin);
//输入输出端口及变量定义
output [7 : 0] s;
output cout;
input [7 : 0] a, b;
input cin;
wire [6 : 0] carry;
//采用结构描述的方式实现一个8位加法器
fulladder m0(s[0], carry[0], a[0], b[0], cin);
fulladder m1(s[1], carry[1], a[1], b[1], carry[0]);
fulladder m2(s[2], carry[2], a[2], b[2], carry[1]);
fulladder m3(s[3], carry[3], a[3], b[3], carry[2]);
fulladder m4(s[4], carry[4], a[4], b[4], carry[3]);
fulladder m5(s[5], carry[5], a[5], b[5], carry[4]);
fulladder m6(s[6], carry[6], a[6], b[6], carry[5]);
fulladder m7(s[7], cout, a[7], b[7], carry[6]);
endmodule
//1位全加器模块
module fulladder(s, cout, a, b, cin);
//输入输出端口定义
output s, cout;
input a, b, cin;
//采用行为描述的方式实现1位全加器
assign s = a ^ b ^ cin;
assign cout = a & b | a & cin | b & cin;
// assign{cout,s} = x+y+cin;
endmodule
4.计数器0~Q(Q<2n)
module counter(
input clk,rst_n;
output [n:0] cnt);
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <=0;
else begin
if(cnt<=Q)
cnt <= cnt +1;
else
cnt <=0;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 0;
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
assign add_cnt = 1;
assign end_cnt = add_cnt && cnt==Q ;
设计一个2位十进制的循环计数器,从0到99,然后再回到0.输出为out0和out1,分别表示十进制数的高位和低位
`timescale 1ns / 1ps
module Test1030(clk,rst,out0,out1,data);
input clk;
input rst;
output reg [3:0] out0;
output reg [3:0] out1;
output reg [7:0] data;
always @(posedge clk or negedge rst)
if(!rst)
begin
out0<=0;
out1<=0;
end
else
begin
if(out0= =9)
begin
out0<=0;
out1<=out1+1;
end
else
out0<=out0+1;
if(out1==10)
out1<=0;
else
out1=out1;
end
assign data=(10*(out1))+out0;
endmodule
5.分频
module practice_demo(
input clk,
input arst,
output clk_div
);
parameter N = 5;
reg [2:0] cnt;
reg clk_a;
reg clk_b;
wire clk_c;
always@(posedge clk or posedge arst)
begin
if(arst)
cnt <= 0;
else if(cnt == N-1)
cnt <= 0;
else
cnt <= cnt + 1;
end
always@(posedge clk or posedge arst)
begin
if(arst)
clk_a<= 0;
else if(cnt == (N-1)/2 || cnt == N-1)
clk_a<= ~clk_a;
else
clk_a<= clk_a;
end
always@(negedge clk or posedge arst)
begin
if(arst)
clk_b <= 0;
else
clk_b <= clk_a;
end
assign clk_c = clk_a | clk_b;
//N[0]=1奇数,否则偶数
assign clk_div = N[0] ? clk_c : clk_a;
endmodule
6.序列检测10010
module detector(clk, reset, d, y);
input clk, reset, d;
output y;
reg [2 : 0] cstate,nstate;
wire y;
parameter idle = 3'b000, s1 = 3'b001, s2 = 3'b010, s3 = 3'b011,s4 = 3'b100, s5 = 3'b101, s6 = 3'b110, s7 = 3'b111;
//状态机实现
always@(posedge clk or posedge reset)
if(reset)
cstate <= idle;
else
cstate <= nstate;
end
always @(*)
begin
case(cstate)
idle: begin
if(d == 1) nstate <= s1;
else nstate <= idle;
end
s1: begin
if(d == 0) nstate <= s2;
else nstate <= s1;
end
s2: begin
if(d == 0) nstate <= s3;
else nstate <= s1;
end
s3: begin
if(d == 1) nstate <= s4;
else nstate <= idle;
end
s4: begin
if(d == 0) nstate <= s5;
else nstate <= s1;
end
s5: begin
if(d == 1) nstate <= s1;
else nstate <= idle;
end
default: nstate <= idle;
endcase
end
end
mealy: assign y = (state == s4 && d == 0) ? 1‘b1 : 1‘b0;
moore: assign y = (state == s5) ? 1‘b1 : 1‘b0;
endmodule
7.异步复位同步释放
module system_ctrl
( input wire clk , //时钟,50Mhz
input wire rst_n , //复位,低电平有效
input wire a , //输入信号
output reg b //输出信号
);
//== 异步复位的同步化设计
reg sys_rst_n_r;
reg sys_rst_n;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
sys_rst_n_r <= 0;
sys_rst_n <= 0;
end
else begin
sys_rst_n_r <= 1;
sys_rst_n <= sys_rst_n_r;
end
end
always @(posedge clk or negedge sys_rst_n) begin
if(!sys_rst_n)
b <= 0;
else
b <= a;
end
endmodule
8.高电平的个数
module test (
input wire clk ,
input wire rst_n ,
input wire [12:0] data ,
output wire [15:0] num
);
reg [ 3:0] i
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
num = 0;
end
else begin
num = 0; //注意清0
for(i=0;i<13;i=i+1)
if(data[i])
num = num + 1; //注意是阻塞赋值
end
end
endmodule
9.串并转换
module left_shifter_reg
(
input clk ,
input rst_n ,
input din ,
output reg [7:0] dout
);
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
dout <= 8'b0;
else
dout <= {dout[6:0], din};
end
endmodule
10.并串转换
module right_shifter_reg
(
input clk ,
input rst_n ,
input [7:0] din ,
input din_vld ,
output dout
);
reg [7:0] shift ;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
shift <= 8'b0;
else if(din_vld) //将值寄存住
shift <= din;
else
shift <= {shift[0], shift[7:1]}; //不断右移
end
assign dout = shift[0];//不断输出
endmodule
11.同步FIFO
module fifo(datain, rd, wr, rst, clk, dataout, full, empty);
input [7:0] datain;
input rd, wr, rst, clk;
output [7:0] dataout;
output full, empty;
wire [7:0] dataout;
reg full_in, empty_in;
reg [7:0] mem [15:0];
reg [3:0] rp, wp;
assign full = full_in;
assign empty = empty_in;
// memory read out
assign dataout = mem[rp];
// memory write in
always@(posedge clk) begin
if(wr && ~full_in) mem[wp]<=datain;
end
// memory write pointer increment
always@(posedge clk or negedge rst) begin
if(!rst) wp<=0;
else begin
if(wr && ~full_in) wp<= wp+1'b1;
end
end
// memory read pointer increment
always@(posedge clk or negedge rst)begin
if(!rst) rp <= 0;
else begin
if(rd && ~empty_in) rp <= rp + 1'b1;
end
end
// Full signal generate
always@(posedge clk or negedge rst) begin
if(!rst) full_in <= 1'b0;
else begin
if( (~rd && wr)&&((wp==rp-1)||(rp==4'h0&&wp==4'hf)))
full_in <= 1'b1;
else if(full_in && rd) full_in <= 1'b0;
end
end
// Empty signal generate
always@(posedge clk or negedge rst) begin
if(!rst) empty_in <= 1'b1;
else begin
if((rd&&~wr)&&(rp==wp-1 || (rp==4'hf&&wp==4'h0)))
empty_in<=1'b1;
else if(empty_in && wr) empty_in<=1'b0;
end
end
endmodule
12.异步FIFO
module asFIFO
(parameter DATA_W = 8 //数据位宽
parameter ADDR_W = 4 //地址位宽)
(input rst_n //复位
Input wr_clk ,//写时钟
input wr_en, //写使能
input [DATA_W-1:0] wr_data ,//写数据
output wr_full,//写满
//FIFO读 -
Input rd_clk ,//读时钟
input rd_en ,//读使能
output reg [DATA_W-1:0] rd_data, //读数据
output rd_empt //读空);
reg [ADDR_W :0] wr_addr_ptr ; //写指针,多1位
reg [ADDR_W :0] rd_addr_ptr ; //读指针,多1位
wire [ADDR_W :0] wr_addr_gray ; //写地址_格雷码
reg [ADDR_W :0] wr_addr_gray_r ; //写地址打拍
reg [ADDR_W :0] wr_addr_gray_rr ; //写地址打拍
wire [ADDR_W :0] rd_addr_gray ; //读地址_格雷码
reg [ADDR_W :0] rd_addr_gray_r ; //读地址打拍
reg [ADDR_W :0] rd_addr_gray_rr ; //读地址打拍
wire [ADDR_W-1:0] wr_addr ; //写地址
wire [ADDR_W-1:0] rd_addr ; //读地址
reg [DATA_W-1:0] ram[2**ADDR_W-1:0] ; //ram,地址位宽4,共16个
//== 地址指针
always @(posedge wr_clk or negedge rst_n) begin
if(!rst_n) begin
wr_addr_ptr <= 0;
end
else if(wr_en & (!wr_full)) begin
wr_addr_ptr <= wr_addr_ptr + 1;
end
end
always @(posedge rd_clk or negedge rst_n) begin
if(!rst_n) begin
rd_addr_ptr <= 0;
end
else if(rd_en & (!rd_empty)) begin
rd_addr_ptr <= rd_addr_ptr + 1;
end
end
//== 空满信号, //-- 格雷码转换
assign wr_addr_gray = (wr_addr_ptr>>1) ^ wr_addr_ptr;
assign rd_addr_gray = (rd_addr_ptr>>1) ^ rd_addr_ptr;
//-- 跨时钟域,打两拍
always @(posedge wr_clk) begin
rd_addr_gray_r <= rd_addr_gray;
rd_addr_gray_rr <= rd_addr_gray_r;
end
always @(posedge rd_clk) begin
wr_addr_gray_r <= wr_addr_gray;
wr_addr_gray_rr <= wr_addr_gray_r;
end
-- 写满标志:高2位不同,其余位相同
Assign wr_full= (wr_addr_gray == ({~rd_addr_gray_rr[ADDR_W-:2],rd_addr_gray_rr[ADDR_W-2:0]}));
//-- 读空标志:读写地址相同
assign rd_empty = (rd_addr_gray == wr_addr_gray_rr);
//== ram读写//-- 读写地址
assign wr_addr = wr_addr_ptr[ADDR_W-1:0];
assign rd_addr = rd_addr_ptr[ADDR_W-1:0];
//-- 写数据
integer i;
always @(posedge wr_clk or negedge rst_n) begin
if(!rst_n) begin
for(i=0; i<2**ADDR_W; i=i+1)
ram[i] <= 0;
end
else if(wr_en & (!wr_full)) begin
ram[wr_addr] <= wr_data;
end
end
//-- 读数据
always @(posedge rd_clk or negedge rst_n) begin
if(!rst_n) begin
rd_data <= 0;
end
else if(rd_en & (!rd_empty)) begin
rd_data <= ram[rd_addr];
end
end
endmodule
13.单bit信号进行毛刺滤除
module filter(
input clk,
input rst_n,
input data_in,
output reg data_out
);
reg data_in_r;
wire data_edge;
reg [2:0]cnt;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
data_in_r <= 1'b0;
else
data_in_r <= data_in;
end
assign data_edge = data_in ^ data_in_r;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 'd0;
else if(data_edge)
cnt <= 'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
data_out <= 1'b0;
else if(&cnt)
data_out <= data_in_r;
else
data_out <= data_out;
end
endmodule
14.跨时钟域
module Sync_Pulse
(
input clka,
input clkb,
input rst_n,
input pulse_ina, //脉冲或电平信号都可以
output pulse_outb, //脉冲信号
output signal_outb //电平信号
);
reg signal_a;
reg signal_a_r1;
reg signal_a_r2;
reg signal_b;
reg signal_b_r1;
//--------------------------------------------------------
//-- a时钟域生成展宽信号
//--------------------------------------------------------
always @(posedge clka or negedge rst_n)begin
if(!rst_n)begin
signal_a <= 1'b0;
end
else if(pulse_ina) begin //检测到脉冲
signal_a <= 1'b1; //拉高
end
else if(signal_a_r2) begin //同步到b后同步回a
signal_a <= 1'b0; //拉低,展宽使命完成
end
end
//--------------------------------------------------------
//-- 展宽信号同步到b时钟域再同步回a时钟域
//--------------------------------------------------------
always @(posedge clkb or negedge rst_n)begin
if(!rst_n)begin
signal_b <= 1'b0;
signal_b_r1 <= 1'b0;
end
else begin
signal_b <= signal_a;
signal_b_r1 <= signal_b;
end
end
always @(posedge clka or negedge rst_n)begin
if(!rst_n)begin
signal_a_r1 <= 1'b0;
signal_a_r2 <= 1'b0;
end
else begin
signal_a_r1 <= signal_b_r1;
signal_a_r2 <= signal_a_r1;
end
end
//-- 脉冲信号输出,上升沿检测
assign pulse_outb = ~signal_b_r1 & signal_b;
//-- 电平信号输出,b时钟域展宽信号
assign signal_outb = signal_b_r1;
endmodule
15.按键消抖
module key_filter
//---------------------<参数定义>---------------------------------------
#(
parameter TIME_20MS = 1000000 , //20ms时间
parameter TIME_W = 20 , //20ms时间位宽
parameter KEY_W = 4 //按键个数)
//---------------------<端口声明>---------------------------------------
(
input clk , //时钟,50Mhz
input rst_n , //复位,低电平有效
input [KEY_W-1:0] key , //按键输入
output reg [KEY_W-1:0] key_vld //按键消抖后的输出
);
//---------------------<信号定义>---------------------------------------
reg [TIME_W-1:0] cnt ;
wire add_cnt ;
wire end_cnt ;
reg [KEY_W -1:0] key_r0 ;
reg [KEY_W -1:0] key_r1 ;
reg flag ;
//----------------------------------------------------------------------
//-- 信号同步 + 消除亚稳态
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
key_r0 <= 0;
key_r1 <= 0;
end
else begin
key_r0 <= key; //信号同步
key_r1 <= key_r0; //打拍,防亚稳态
end
end
//----------------------------------------------------------------------
//-- 20ms计时
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 0;
else if(add_cnt)begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
else
cnt <= cnt;
end
assign add_cnt = flag==0 && key_r1!=0 ; //允许计数 且 按键按下
assign end_cnt = add_cnt && cnt==TIME_20MS-1; //计到20ms
/计满指示
always @(posedge clk or negedge rst_n)begin
if(!rst_n) //复位
flag <= 0; //flag=0允许计数
else if(end_cnt) //20ms到
flag <= 1; //flag=1不再计数
else if(key_r1==0) //按键松开
flag <= 0; //flag=0,为下次计数做准备
else //否则
flag <= flag; //维持自身
end
//----------------------------------------------------------------------
//-- 按键消抖完成,输出按键有效信号
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
key_vld <= 0;
else if(end_cnt) //20ms到
key_vld <= key_r1; //按键已消抖,可以使用
else
key_vld <= 0;
end
endmodule
16.无毛刺的时钟切换
module glitch_free (
input clk0, // Clock
input clk1,
input select,
input rst_n, // Asynchronous reset active low
output clkout
);
wire mid_clk0;
reg mid_clk0_r1, mid_clk0_r2, mid_clk0_r2n;
wire mid_clk1;
reg mid_clk1_r1, mid_clk1_r2, mid_clk1_r2n;
assign mid_clk1 = select & mid_clk0_r2n;
assign mid_clk0 = ~select & mid_clk1_r2n;
//第一级触发器用上升沿采样,选择信号与反馈信号的与运算
always@(posedge clk1 or negedge rst_n) begin
if(~rst_n) mid_clk1_r1 <= 0;
else mid_clk1_r1 <= mid_clk1;
end
//第二级触发器用下降沿采样
always@(negedge clk1 or negedge rst_n) begin
if(~rst_n) begin
mid_clk1_r2 <= 0;
mid_clk1_r2n <= 1;
end
else begin
mid_clk1_r2 <= mid_clk1_r1;
mid_clk1_r2n <= ~mid_clk1_r1;
end
end
//第一级触发器用上升沿采样,选择信号与反馈信号的与运算
always@(posedge clk0 or negedge rst_n) begin
if(~rst_n) mid_clk0_r1 <= 0;
else mid_clk0_r1 <= mid_clk0;
end
//第二级触发器用下降沿采样
always@(negedge clk0 or negedge rst_n) begin
if(~rst_n) begin
mid_clk0_r2 <= 0;
mid_clk0_r2n <= 1;
end
else begin
mid_clk0_r2 <= mid_clk0_r1;
mid_clk0_r2n <= ~mid_clk0_r1;
end
end
wire mid_clk11, mid_clk00;
assign mid_clk11 = clk1 & mid_clk1_r2;
assign mid_clk00 = clk0 & mid_clk0_r2;
assign clkout = mid_clk11 | mid_clk00;
endmodule