博客首页:安静到无声
⛳️ 欢迎关注 ❤️ 点赞 收藏 ✏️ 留言
系列专栏:Verilog学习
由于HDLBits刷题并不方便,在这里给大家强烈推荐一款嵌入式硬件模拟面试、刷题神器——牛客网( [ Verilog,C等基础,更有一些硬件知识点拨 )
❤️ 点击免费注册和我一起刷题吧
`timescale 1ns/1ns
module mux4_1(
input [ 1:0] d1,d2,d3,d0 ,
input [ 1:0] sel ,
output [ 1:0] mux_out
);
//*************code***********//
/*
reg [ 1:0] state ;
always @(*) begin
case (sel)
2'b00:state = d3;
2'b01:state = d2;
2'b11:state = d0;
2'b10:state = d1;
default:state = d3;
endcase
end
assign mux_out = state;
*/
assign mux_out = sel[1]==1?(sel[0]==1?d0:d1):(sel[0]==1?d2:d3);
//*************code***********//
endmodule
VL2 异步复位的串联T触发器
`timescale 1ns/1ns
module Tff_2 (
input wire data, clk, rst ,
output reg q
);
reg data1 ;
always @(posedge clk or negedge rst) begin
if(!rst) begin
data1 <= 1'b0;
end else begin
if (data) begin
data1 <= !data1;
end
else begin
data1 <= data1;
end
end
end
always @(posedge clk or negedge rst) begin
if(!rst) begin
q <= 1'b0;
end else begin
if (data1) begin
q <= !q;
end else begin
q <= q;
end
end
end
endmodule
LV3 奇偶校验
`timescale 1ns/1ns
module odd_sel(
input [ 31:0] bus ,
input sel ,
output check
);
//*************code***********//
reg state;
always @(*) begin
case (sel)
1'b1:
if(^bus == 1) begin
state = 1;
end
else begin
state = 0;
end
1'b0:
if (^bus == 0) begin
state = 1;
end
else begin
state = 0;
end
default: state = 0;
endcase
end
assign check = state;
endmodule
VL4 移位运算与乘法
`timescale 1ns/1ns
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
reg [1:0] state;
reg [7:0] din;
always @(posedge clk or negedge rst) begin
if(!rst)begin
out <= 11'b0;
state <= 2'b00;
input_grant <= 0;
din <= 0;
end
else begin
case (state)
2'b00:begin
input_grant <= 1;
din <= d;
out <= d;
//out <= (din<<2) - din;
state <= 2'b01;
end
2'b01: begin
out <= (din<<2) - din;
input_grant <= 0;
state <= 2'b10;
end
2'b10:begin
out <= (din<<3) - din;
input_grant <= 0;
state <= 2'b11;
end
2'b11: begin
out <= (din<<3);
input_grant <= 0;
state <= 2'b00;
end
default:begin
state <= 2'b00;
input_grant <= 0;
end
endcase
end
end
endmodule
LV5 位拆分与运算
`timescale 1ns/1ns
module data_cal(
input clk ,
input rst ,
input [ 15:0] d ,
input [ 1:0] sel ,
output [ 4:0] out ,
output validout
);
reg [ 4:0] out_map ;
reg [ 15:0] d_luck ;
reg validout_tmp ;
always @(posedge clk or negedge rst) begin
if(!rst)begin
out_map <= 5'd0;
validout_tmp<=1'b0;
end
else begin
case (sel)
2'd0: begin
d_luck <= d;
validout_tmp<=1'b0;
out_map <= 5'd0;
end
2'd1: begin
out_map <= d_luck[3:0] + d_luck[7:4];
validout_tmp<=1'b1;
end
2'd2: begin
out_map <= d_luck[3:0] + d_luck[11:8];
validout_tmp<=1'b1;
end
2'd3: begin
out_map <= d_luck[3:0] + d_luck[15:12];
validout_tmp<=1'b1;
end
default:begin
out_map <= 5'd0;
validout_tmp<=1'b0;
end
endcase
end
end
assign out = out_map;
assign validout = validout_tmp;
endmodule
VL6 多功能数据处理器
`timescale 1ns/1ns
module data_select(
input clk ,
input rst_n ,
input signed [ 7:0] a ,
input signed [ 7:0] b ,
input [ 1:0] select ,
output reg signed [ 8:0] c
);
always @(posedge clk or negedge rst_n)
if(!rst_n)
c <= 9'd0;
else case(select)
2'b00: c <= a;
2'b01: c <= b;
2'b10: c <= a+b;
2'b11: c <= a-b;
default: c <= 9'd0;
endcase
endmodule
VL7 求两个数的差值
`timescale 1ns/1ns
module data_minus(
input clk ,
input rst_n ,
input [ 7:0] a ,
input [ 7:0] b ,
output reg [ 8:0] c
);
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
c <= 9'b0;
end
else begin
if (a>b) begin
c <= a - b;
end
else if(a <= b) begin
c <= b - a;
end
end
end
endmodule
VL8 使用generate…for语句简化代码
`timescale 1ns/1ns
module gen_for_module(
input [ 7:0] data_in ,
output [ 7:0] data_out
);
genvar i;
generate
for(i = 0; i < 8; i = i + 1)
begin : bit_reverse
assign data_out[i] = data_in[7 - i];
end
endgenerate
endmodule
VL9 使用子模块实现三输入数的大小比较
`timescale 1ns/1ns
module main_mod(
input clk ,
input rst_n ,
input [ 7:0] a ,
input [ 7:0] b ,
input [ 7:0] c ,
output [ 7:0] d
);
wire [ 7:0] m,n ;
sub_module sub_ab(
.clk (clk ),
.rst_n (rst_n ),
.a (a ),
.b (b ),
.c (m )
);
sub_module sub_mc(
.clk (clk ),
.rst_n (rst_n ),
.a (b ),
.b (c ),
.c (n )
);
sub_module sub_mn(
.clk (clk ),
.rst_n (rst_n ),
.a (m ),
.b (n ),
.c (d )
);
endmodule
module sub_module (
input clk ,
input rst_n ,
input [ 7:0] a ,
input [ 7:0] b ,
output reg [ 7:0] c
);
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
c <= 8'd0;
end else begin
if(a <= b) begin
c <= a;
end
else begin
c <= b;
end
end
end
endmodule
VL10 使用函数实现数据大小端转换
`timescale 1ns/1ns
module function_mod(
input clk ,
input rst_n ,
input [ 3:0] a ,
input [ 3:0] b ,
output [ 3:0] c ,
output [ 3:0] d
);
function [3:0] reverse;
input [ 3:0] data_in ;
integer i;
begin
for (i = 0;i<4 ;i = i + 1 ) begin
reverse[i] = data_in[3-i];
end
end
endfunction
assign c = reverse(a);
assign d = reverse(b);
endmodule
VL11 4位数值比较器电路
`timescale 1ns/1ns
module comparator_4(
input [3:0] A ,
input [3:0] B ,
output wire Y2 , //A>B
output wire Y1 , //A=B
output wire Y0 //A
);
reg Y2_tmp,Y1_tmp,Y0_tmp;
always @(A or B) begin
if(A > B) begin
Y2_tmp = 1;
Y1_tmp = 0;
Y0_tmp = 0;
end
else if (A < B) begin
Y2_tmp = 0;
Y1_tmp = 0;
Y0_tmp = 1;
end
else if(A == B) begin
Y2_tmp = 0;
Y1_tmp = 1;
Y0_tmp = 0;
end
end
assign Y2 = Y2_tmp;
assign Y1 = Y1_tmp;
assign Y0 = Y0_tmp;
endmodule
VL12 4bit超前进位加法器电路
`timescale 1ns/1ns
module lca_4(
input [3:0] A_in ,
input [3:0] B_in ,
input C_1 ,
output wire CO ,
output wire [3:0] S
);
wire [3:0] G_i;
wire [3:0] P_i;
wire [3:0] C_i;
assign G_i = A_in & B_in;
assign P_i = A_in ^ B_in;
assign C_i[0] = G_i[0] | P_i[0]&C_1;
assign C_i[1] = G_i[1] | P_i[1]&G_i[0] | P_i[1]&P_i[0]&C_1;
assign C_i[2] = G_i[2] | P_i[2]&G_i[1] | P_i[2]&P_i[1]&G_i[0] | P_i[2]&P_i[1]&P_i[0]&C_1;
assign C_i[3] = G_i[3] | P_i[3]&G_i[2] | P_i[3]&P_i[2]&G_i[1] | P_i[3]&P_i[2]&P_i[1]&(G_i[0] | P_i[0]&C_1);
assign S[0] = P_i[0] ^ C_1;
assign S[1] = P_i[1] ^ C_i[0];
assign S[2] = P_i[2] ^ C_i[1];
assign S[3] = P_i[3] ^ C_i[2];
assign CO = C_i[3];
endmodule
VL13 优先编码器电路①
`timescale 1ns/1ns
module encoder_0(
input [ 8:0] I_n ,
output reg [ 3:0] Y_n
);
always @(*) begin
casex (I_n)
9'b1_1111_1111:Y_n <= 4'b1111;
9'b0_xxxx_xxxx:Y_n <= 4'b0110;
9'b1_0xxx_xxxx:Y_n <= 4'b0111;
9'b1_10xx_xxxx:Y_n <= 4'b1000;
9'b1_110x_xxxx:Y_n <= 4'b1001;
9'b1_1110_xxxx:Y_n <= 4'b1010;
9'b1_1111_0xxx:Y_n <= 4'b1011;
9'b1_1111_10xx:Y_n <=4'b1100;
9'b1_1111_110x:Y_n <= 4'b1101;
9'b1_1111_1110:Y_n <= 4'b1110;
default: Y_n <= 4'b1111;
endcase
end
endmodule
VL14 用优先编码器①实现键盘编码电路
`timescale 1ns/1ns
module encoder_0(
input [ 8:0] I_n ,
output reg [ 3:0] Y_n
);
always @(*)begin
casex(I_n)
9'b111111111 : Y_n = 4'b1111;
9'b0xxxxxxxx : Y_n = 4'b0110;
9'b10xxxxxxx : Y_n = 4'b0111;
9'b110xxxxxx : Y_n = 4'b1000;
9'b1110xxxxx : Y_n = 4'b1001;
9'b11110xxxx : Y_n = 4'b1010;
9'b111110xxx : Y_n = 4'b1011;
9'b1111110xx : Y_n = 4'b1100;
9'b11111110x : Y_n = 4'b1101;
9'b111111110 : Y_n = 4'b1110;
default : Y_n = 4'b1111;
endcase
end
endmodule
module key_encoder(
input [ 9:0] S_n ,
output wire [ 3:0] L ,
output wire GS
);
wire [ 3:0] L_tmp ;
encoder_0 encoder_0(
.I_n (S_n[9:1] ),
.Y_n (L_tmp )
);
assign L = ~L_tmp;
assign GS = ((L_tmp == 4'b1111) && (S_n[0] == 1)) ? 0: 1;
endmodule
VL15 优先编码器Ⅰ
`timescale 1ns/1ns
module encoder_83(
input [7:0] I ,
input EI ,
output wire [2:0] Y ,
output wire GS ,
output wire EO
);
assign Y[2] = EI & (I[7] | I[6] | I[5] | I[4]);
assign Y[1] = EI & (I[7] | I[6] | ~I[5]&~I[4]&I[3] | ~I[5]&~I[4]&I[2]);
assign Y[0] = EI & (I[7] | ~I[6]&I[5] | ~I[6]&~I[4]&I[3] | ~I[6]&~I[4]&~I[2]&I[1]);
assign EO = EI&~I[7]&~I[6]&~I[5]&~I[4]&~I[3]&~I[2]&~I[1]&~I[0];
assign GS = EI&(I[7] | I[6] | I[5] | I[4] | I[3] | I[2] | I[1] | I[0]);
//assign GS = EI&(| I);
endmodule
VL16 使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器
`timescale 1ns/1ns
module encoder_83(
input [7:0] I ,
input EI ,
output wire [2:0] Y ,
output wire GS ,
output wire EO
);
assign Y[2] = EI & (I[7] | I[6] | I[5] | I[4]);
assign Y[1] = EI & (I[7] | I[6] | ~I[5]&~I[4]&I[3] | ~I[5]&~I[4]&I[2]);
assign Y[0] = EI & (I[7] | ~I[6]&I[5] | ~I[6]&~I[4]&I[3] | ~I[6]&~I[4]&~I[2]&I[1]);
assign EO = EI&~I[7]&~I[6]&~I[5]&~I[4]&~I[3]&~I[2]&~I[1]&~I[0];
assign GS = EI&(I[7] | I[6] | I[5] | I[4] | I[3] | I[2] | I[1] | I[0]);
//assign GS = EI&(| I);
endmodule
module encoder_164(
input [15:0] A , //分为高8位和低8位
input EI , //使能表示有无按键按下
output wire [3:0] L ,
output wire GS ,
output wire EO
);
wire [2:0] Y_0;
wire [2:0] Y_1;
wire GS_0;
wire EO_0;
wire GS_1;
wire EO_1;
encoder_83 u_0(
.I(A[7:0]),
.EI(EO_1),
.Y(Y_0),
.GS(GS_0),
.EO(EO)
);
encoder_83 u_1(
.I(A[15:8]),
.EI(EI),
.Y(Y_1),
.GS(GS_1),
.EO(EO_1)
);
assign GS = GS_1 | GS_0;
assign L[3] = GS_1;
assign L[2] = Y_1[2] | Y_0[2];
assign L[1] = Y_1[1] | Y_0[1];
assign L[0] = Y_1[0] | Y_0[0];
endmodule
VL21 根据状态转移表实现时序电路
`timescale 1ns/1ns
module seq_circuit(
input A ,
input clk ,
input rst_n,
output wire Y
);
reg q0,q1;
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
q1 <= 0;
end
else begin;
q1 <= (~A)&(~q1)&(q0) | (~A)&(q1)&(~q0) | (A)&(~q1)&(~q0) | (A)&(q1)&(q0);
end
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
q0 <= 0;
end
else begin;
q0 <= ~q0;
end
end
assign Y = q0 & q1;
endmodule
VL22 根据状态转移图实现时序电路
`timescale 1ns/1ns
module seq_circuit(
input C ,
input clk ,
input rst_n,
output wire Y
);
//定义的状态类型
parameter IDLE = 2'b00 ;
parameter GET1 = 2'b01 ;
parameter GET2 = 2'b10 ;
parameter GET3 = 2'b11 ;
//machine variable
reg [1:0] st_next ;
reg [1:0] st_cur ;
//(1) state transfer
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
st_cur <= IDLE ;
end
else begin
st_cur <= st_next ;
end
end
always @(*) begin
case (st_cur)
IDLE:begin
if (C == 0) begin
st_next <= IDLE;
end
else begin
st_next <= GET1;
end
end
GET1:begin
if (C == 1) begin
st_next <= GET1;
end
else begin
st_next <= GET3;
end
end
GET3:begin
if (C == 0) begin
st_next <= GET3;
end
else begin
st_next <= GET2;
end
end
GET2:begin
if (C == 1) begin
st_next <= GET2;
end
else begin
st_next <= IDLE;
end
end
default:st_next <= IDLE;
endcase
end
reg Y_tmp;
always@(*) begin
case (st_cur)
IDLE:begin
Y_tmp <= 1'b0;
end
GET1:begin
Y_tmp <= 1'b0;
end
GET2:begin
if (C == 1) begin
Y_tmp <= 1'b1;
end
else begin
Y_tmp <= 1'b0;
end
end
GET3:begin
if (C == 0) begin
Y_tmp <= 1'b1;
end
end
default: Y_tmp <= 1'b0;
endcase
end
assign Y = Y_tmp;
endmodule
VL23 ROM的简单实现
`timescale 1ns/1ns
module rom(
input clk,
input rst_n,
input [7:0]addr,
output [3:0]data
);
//开辟一个深度为8,位宽为4的空间
reg [3:0] rom_data [7:0];
assign data = rom_data[addr];
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rom_data[0] <= 4'd0;
rom_data[1] <= 4'd2;
rom_data[2] <= 4'd4;
rom_data[3] <= 4'd6;
rom_data[4] <= 4'd8;
rom_data[5] <= 4'd10;
rom_data[6] <= 4'd12;
rom_data[7] <= 4'd14;
end
else begin
rom_data[0] <= 4'd0;
rom_data[1] <= 4'd2;
rom_data[2] <= 4'd4;
rom_data[3] <= 4'd6;
rom_data[4] <= 4'd8;
rom_data[5] <= 4'd10;
rom_data[6] <= 4'd12;
rom_data[7] <= 4'd14;
end
end
endmodule
VL24 边沿检测
`timescale 1ns/1ns
module edge_detect(
input clk,
input rst_n,
input a,
output reg rise,
output reg down
);
reg a_tep;
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
a_tep <= 1'b0;
end
else begin
a_tep <= a;
end
end
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
rise <= 1'b0;
down <= 1'b0;
end
else begin
if (a & ~a_tep) begin
rise <= 1'b1;
down <= 1'b0;
end
else if (~a & a_tep) begin
rise <= 1'b0;
down <= 1'b1;
end
else begin
rise <= 1'b0;
down <= 1'b0;
end
end
end
endmodule
VL25 输入序列连续的序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [7:0] state_cache;
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
state_cache <= 8'b0;
match <= 1'b0;
end
else begin
state_cache <= {state_cache[6:0],a};
if (state_cache == 8'b0111_0001) begin
match <= 1'b1;
end
else begin
match <= 1'b0;
end
end
end
endmodule
VL26 含有无关项的序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [8:0] state_cache;
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
state_cache <= 8'b0;
match <= 1'b0;
end
else begin
state_cache <= {state_cache[7:0],a};
if (state_cache[8:6] == 3'b011 && state_cache[2:0] == 3'b110) begin
match <= 1'b1;
end
else begin
match <= 1'b0;
end
end
end
endmodule
VL27 不重叠序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
);
//定义的状态类型
parameter IDLE = 4'd0 ;
parameter s1 = 4'd1 ;
parameter s2 = 4'd2 ;
parameter s3 = 4'd3 ;
parameter s4 = 4'd4 ;
parameter s5 = 4'd5 ;
parameter s6 = 4'd6 ;
parameter sf1 = 4'd7 ;
parameter sf2 = 4'd8 ;
parameter sf3 = 4'd9 ;
parameter sf4 = 4'd10 ;
parameter sf5 = 4'd11 ;
parameter sf6 = 4'd12 ;
//machine variable
reg [ 3:0] st_next ;
reg [ 3:0] st_cur ;
//(1) state transfer
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
st_cur <= IDLE ;
end
else begin
st_cur <= st_next ;
end
end
always@(st_cur or data) begin
case (st_cur)
IDLE:begin
if(data == 0) begin
st_next = s1;
end
else begin
st_next = sf1;
end
end
s1:begin
if(data == 1) begin
st_next = s2;
end
else begin
st_next = sf2;
end
end
s2:begin
if(data == 1) begin
st_next = s3;
end
else begin
st_next = sf3;
end
end
s3:begin
if(data == 1) begin
st_next = s4;
end
else begin
st_next = sf4;
end
end
s4:begin
if(data == 0) begin
st_next = s5;
end
else begin
st_next = sf5;
end
end
s5:begin
if(data == 0) begin
st_next = s6;
end
else begin
st_next = sf6;
end
end
s6:begin
if(data == 0) begin
st_next = s1;
end
else begin
st_next = sf1;
end
end
sf1:begin
st_next = sf2;
end
sf2:begin
st_next <= sf3;
end
sf3:begin
st_next = sf4;
end
sf4:begin
st_next = sf5;
end
sf5:begin
st_next = sf6;
end
sf6:begin
if (data == 0) begin
st_next = s1;
end
else begin
st_next = sf1;
end
end
default: st_next = IDLE;
endcase
end
always @(*) begin
if (!rst_n) begin
match <= 1'b0;
not_match <= 1'b0;
end else begin
if(st_cur == s6) begin
match <= 1'b1;
not_match <= 1'b0;
end
else if(st_cur == sf6) begin
match <= 1'b0;
not_match <= 1'b1;
end
else begin
match <= 1'b0;
not_match <= 1'b0;
end
end
end
endmodule
VL28 输入序列不连续的序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk ,
input rst_n ,
input data ,
input data_valid ,
output reg match
);
//定义的状态类型
parameter IDLE = 4'd0 ;
parameter s1_0 = 4'd1 ;
parameter s2_01 = 4'd2 ;
parameter s3_011 = 4'd3 ;
parameter s4_0110 = 4'd4 ;
//machine variable
reg [ 3:0] st_next ;
reg [ 3:0] st_cur ;
//(1) state transfer
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
st_cur <= IDLE ;
end
else begin
st_cur <= st_next ;
end
end
always @(st_cur or data or data_valid) begin
case (st_cur)
IDLE:begin
if(data_valid && data == 0) begin
st_next = s1_0;
end
else begin
st_next = IDLE;
end
end
s1_0:begin
if(data_valid) begin
if (data == 1) begin
st_next = s2_01;
end else begin
st_next = s1_0;
end
end
else begin
st_next = s1_0;
end
end
s2_01:begin
if(data_valid) begin
if (data == 1) begin
st_next = s3_011;
end else begin
st_next = s1_0;
end
end
else begin
st_next = s2_01;
end
end
s3_011:begin
if(data_valid) begin
if (data == 0) begin
st_next = s4_0110;
end else begin
st_next = IDLE;
end
end
else begin
st_next = s3_011;
end
end
s4_0110:begin
if(data_valid) begin
if (data == 0) begin
st_next = s1_0;
end else begin
st_next = IDLE;
end
end
else begin
st_next = IDLE;
end
end
default: st_next = IDLE;
endcase
end
always @(st_cur or rst_n) begin
if(!rst_n==1) begin
match <= 1'b0;
end
else if (st_cur == s4_0110) begin
match <= 1'b1;
end
else begin
match <= 1'b0;
end
end
endmodule
VL29 信号发生器
`timescale 1ns/1ns
module signal_generator(
input clk,
input rst_n,
input [1:0] wave_choise,
output reg [4:0]wave
);
endmodule
VL30 数据串转并电路
`timescale 1ns/1ns
module s_to_p(
input clk ,
input rst_n ,
input valid_a ,
input data_a ,
output reg ready_a ,
output reg valid_b ,
output reg [ 5:0] data_b
);
reg [ 5:0] data_cache ;//数据缓存
reg [ 2:0] data_cnt ;//计数器
//计数器 值如果有效加1;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_cnt <= 3'b0;
end else begin
if(valid_a) begin
if(data_cnt == 3'd5) begin
data_cnt <= 0;
end else begin
data_cnt <= data_cnt + 1;
end
end
else begin
data_cnt <= data_cnt;
end
end
end
//有效赋值
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_cache <= 6'b00_0000;
end
else if(valid_a && data_cnt <= 3'd5) begin
data_cache <= {data_a,data_cache[5:1]};
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_b <= 6'd0;
end
else if(data_cnt == 3'd5) begin
data_b <= {data_a,data_cache[5:1]};
end
else begin
data_b <= data_b;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
valid_b <= 1'b0;
end
else if (data_cnt == 3'd5) begin
valid_b <= 1'd1;
end else begin
valid_b <= 1'd0;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
ready_a <= 1'd0;
end else begin
ready_a <= 1'd1;
end
end
endmodule
VL31 数据累加输出
`timescale 1ns/1ns
module valid_ready(
input clk ,
input rst_n ,
input [ 7:0] data_in ,
input valid_a ,
input ready_b ,
output ready_a ,
output reg valid_b ,
output reg [ 9:0] data_out
);
reg [ 1:0] data_cnt ;
//计数器用于表示计算是否满
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_cnt <= 2'b0;
end else begin
if(valid_a && ready_a) begin
if(data_cnt == 2'd3) begin
data_cnt <= 0;
end else begin
data_cnt <= data_cnt + 1;
end
end
else begin
data_cnt <= data_cnt;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_out <= 10'd0;
end
else if(valid_a && ready_a) begin
if(data_cnt == 2'd0) begin
data_out <= data_in;
end else begin
data_out <= data_out + data_in;
end
end
else begin
data_out <= data_out;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
valid_b <= 1'b0;
end else begin
if(data_cnt == 2'd3 && valid_a && ready_a) begin
valid_b <= 1'b1;
end
else if (valid_b && ready_b) begin
valid_b <= 1'b0;
end
else begin
valid_b <= valid_b;
end
end
end
assign ready_a = ~valid_b | ready_b;
endmodule
VL32 非整数倍数据位宽转换24to128
`timescale 1ns/1ns
module width_24to128(
input clk ,
input rst_n ,
input valid_in ,
input [ 23:0] data_in ,
output reg valid_out ,
output reg [ 127:0] data_out
);
reg [3:0] data_cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_cnt <= 3'd0;
end else begin
if(valid_in) begin
if(data_cnt == 4'd15) begin
data_cnt <= 4'd0;
end else begin
data_cnt <= data_cnt + 1'd1;
end
end else begin
data_cnt <= data_cnt;
end
end
end
reg [120-1:0] data_buff;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_buff <= 120'd0;
end else if(valid_in) begin
data_buff <= {data_buff[95:0],data_in};
end
else begin
data_buff <= data_buff;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_out <= 128'd0;
valid_out <= 1'd0;
end else begin
if(valid_in && data_cnt == 4'd5) begin
data_out <= {data_buff,data_in[23:16]};
valid_out <= 1'd1;
end
else if(valid_in && data_cnt == 4'd10) begin
data_out <= {data_buff[111:0],data_in[23:8]};
valid_out <= 1'd1;
end
else if(valid_in && data_cnt == 4'd15) begin
data_out <= {data_buff[103:0],data_in};
valid_out <= 1'd1;
end
else begin
valid_out <= 1'd0;
end
end
end
endmodule
VL33 非整数倍数据位宽转换8to12
`timescale 1ns/1ns
/*
valid_in表示输入有效,当为1表示输入有效,当为0上表述输入数据无效
*/
module width_8to12(
input clk ,
input rst_n ,
input valid_in ,
input [ 7:0] data_in ,
output reg valid_out ,
output reg [ 11:0] data_out
);
reg [1:0] data_cnt ;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_cnt <= 2'b0;
end else begin
if (valid_in) begin
if (data_cnt == 2'd2) begin
data_cnt <= 2'd0;
end
else begin
data_cnt <= data_cnt + 1'd1;
end
end
else begin
data_cnt <= data_cnt;
end
end
end
reg [ 7:0] data_buff ;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_buff <= 8'd0;
end else begin
if (valid_in) begin
data_buff <= data_in;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_out <= 12'd0;
valid_out <= 1'd0;
end else begin
if(data_cnt == 2'd1 && valid_in) begin
data_out <= {data_buff,data_in[7:4]};
valid_out <= 1'd1;
end
else if(data_cnt == 2'd2 && valid_in) begin
data_out <= {data_buff[3:0],data_in};
valid_out <= 1'd1;
end
else begin
valid_out <= 1'd0;
end
end
end
endmodule
VL34 整数倍数据位宽转换8to16
`timescale 1ns/1ns
module width_8to16(
input clk ,
input rst_n ,
input valid_in ,
input [ 7:0] data_in ,
output reg valid_out ,
output reg [ 15:0] data_out
);
reg data_cnt ;
//计数器用于表示计算是否满
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_cnt <= 1'b0;
end
else begin
if(valid_in) begin
data_cnt <= data_cnt + 1'b1;
end
else begin
data_cnt <= data_cnt;
end
end
end
reg [7:0] data_reg;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_out <= 16'b0;
valid_out <= 1'b0;
end else begin
if (valid_in) begin
if (data_cnt == 0) begin
data_reg <= data_in;
valid_out <= 1'b0;
end else begin
data_out <= {data_reg,data_in};
valid_out <= 1'b1;
end
end else begin
valid_out <= 1'b0;
end
end
end
endmodule
VL35 状态机-非重叠的序列检测
`timescale 1ns/1ns
module sequence_test1(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
//*************code***********//
parameter IDLE = 3'b000;
parameter s1_1 = 3'b001;
parameter s2_10 = 3'b010;
parameter s3_101 = 3'b011;
parameter s4_1011 = 3'b100;
parameter s5_10111 = 3'b101;
//machine variable
reg [ 2:0] st_next ;
reg [ 2:0] st_cur ;
//(1) state transfer
always @(posedge clk or negedge rst) begin
if (!rst) begin
st_cur <= IDLE ;
end
else begin
st_cur <= st_next ;
end
end
always @(*) begin
case (st_cur)
IDLE: begin
st_next = data?s1_1:IDLE;
end
s1_1: begin
st_next = data?s1_1:s2_10;
end
s2_10: begin
st_next = data?s3_101:IDLE;
end
s3_101: begin
st_next = data?s4_1011:s2_10;
end
s4_1011: begin
st_next = data?s5_10111:s2_10;
end
s5_10111:begin
st_next = data?s1_1:IDLE;
end
default: st_next = IDLE;
endcase
end
always @(*) begin
if(!rst) begin
flag <= 1'b0;
end
else if(st_cur == s5_10111) begin
flag <= 1'b1;
end
else begin
flag <= 1'b0;
end
end
//*************code***********//
endmodule
VL36 状态机-重叠序列检测
`timescale 1ns/1ns
module sequence_test2(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
//*************code***********//
parameter S0=0, S1=1, S2=2, S3=3, S4=4;
reg [2:0] state, nstate;
always@(posedge clk or negedge rst) begin
if(~rst)
state <= S0;
else
state <= nstate;
end
always@(*) begin
if(~rst)
nstate <= S0;
else
case(state)
S0 : nstate <= data? S1: S0;
S1 : nstate <= data? S1: S2;
S2 : nstate <= data? S3: S0;
S3 : nstate <= data? S4: S2;
S4 : nstate <= data? S1: S2;
default: nstate <= S0;
endcase
end
always@(posedge clk or negedge rst) begin
if(~rst)
flag <= 0;
else
flag <= state==S4;
end
//*************code***********//
endmodule
VL37 时钟分频(偶数)
`timescale 1ns/1ns
module even_div
(
input wire rst ,
input wire clk_in ,
output wire clk_out2 ,
output wire clk_out4 ,
output wire clk_out8
);
//*************code***********//
reg [ 1:0] clk_cnt ;
reg s_1,s_2,s_3 ;
always @(posedge clk_in or negedge rst) begin
if(!rst) begin
clk_cnt <= 2'b0;
end
else if (clk_cnt == 2'b11) begin
clk_cnt <= 2'b0;
end else begin
clk_cnt <= clk_cnt + 1'b1;
end
end
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
s_1 <= 1'b0;
s_2 <= 1'b0;
s_3 <= 1'b0;
end else begin
if(clk_cnt==2'd0 ||clk_cnt==2'd1||clk_cnt==2'd2||clk_cnt==2'd3) begin
s_1 <= ~s_1;
end
if (clk_cnt == 2'd0 || clk_cnt == 2'd2) begin
s_2 <= ~s_2;
end
if(clk_cnt == 2'd0) begin
s_3 <= ~s_3;
end
end
end
assign clk_out2 = s_1;
assign clk_out4 = s_2;
assign clk_out8 = s_3;
//*************code***********//
endmodule
VL38 自动贩售机1
`timescale 1ns/1ns
module seller1(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire d3 ,
output reg out1,
output reg [1:0]out2
);
//*************code***********//
localparam IDLE = 0,
HALF = 1,
ONE = 2,
ONE_HALF = 3,
TWO = 4,
TWO_HALF = 5,
THREE =6;
reg[2:0] curr_state,next_state;
always @(posedge clk or negedge rst)begin
if(~rst)
curr_state <= IDLE;
else
curr_state <= next_state;
end
always @(*)begin
case(curr_state)
IDLE :begin
next_state =d1? HALF:
d2? ONE:
d3? TWO:
next_state;
end
HALF :begin
next_state =d1? ONE:
d2? ONE_HALF:
d3? TWO_HALF:
next_state;
end
ONE :begin
next_state =d1? ONE_HALF:
d2? TWO:
d3? THREE:
next_state;
end
ONE_HALF :next_state =IDLE;
TWO :next_state =IDLE;
TWO_HALF :next_state =IDLE;
THREE :next_state =IDLE;
default :next_state =IDLE;
endcase
end
always @(posedge clk or negedge rst)begin
if(~rst)begin
out1 <= 0;
out2 <= 0;
end else begin
case(next_state)
ONE_HALF:begin
out1 <= 1'b1; out2<=0;
end
TWO :begin
out1 <= 1'b1; out2<=1;
end
TWO_HALF:begin
out1 <= 1'b1; out2<=2;
end
THREE :begin
out1 <= 1'b1; out2<=3;
end
default :begin
out1 <= 1'b0; out2<=0;
end
endcase
end
end
//*************code***********//
endmodule
VL39 自动贩售机2
`timescale 1ns/1ns
module seller2(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire sel ,
output reg out1,
output reg out2,
output reg out3
);
//*************code***********//
//*************code***********//
endmodule
VL40 占空比50%的奇数分频
`timescale 1ns/1ns
module odo_div_or
(
input wire rst ,
input wire clk_in ,
output wire clk_out7
);
//*************code***********//
//*************code***********//
reg [ 2:0] clk_cnt ;
always @(posedge clk_in or negedge rst) begin
if(!rst) begin
clk_cnt <= 3'b0;
end
else if (clk_cnt == 3'd6) begin
clk_cnt <= 3'b0;
end else begin
clk_cnt <= clk_cnt + 1'b1;
end
end
reg
s_1 ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
s_1 <= 1'b0;
end
else begin
if(clk_cnt == 3'd6) begin
s_1 <= ~s_1;
end
else begin
s_1 <= s_1;
end
end
end
always @(negedge clk_in or negedge rst) begin
if (!rst) begin
s_1 <= 1'b0;
end
else begin
if(clk_cnt == 3'd3) begin
s_1 <= ~s_1;
end
else begin
s_1 <= s_1;
end
end
end
assign clk_out7 = s_1;
//*************code***********//
endmodule
VL41 任意小数分频
`timescale 1ns/1ns
module div_M_N(
input wire clk_in ,
input wire rst ,
output wire clk_out
);
parameter M_N = 8'd87 ;
parameter c89 = 8'd24 ;//8/9时钟切换点
parameter div_e = 5'd8 ;//偶数周期
parameter div_o = 5'd9 ;//奇数周期
//*************code***********//
reg [ 6:0] data_cnt ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
data_cnt <= 7'd0;
end else begin
if(data_cnt == 7'd86) begin
data_cnt <= 0;
end else begin
data_cnt <= data_cnt + 1'd1;
end
end
end
reg clk_out_ache ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
clk_out_ache <= 1'd0;
end else begin
if(data_cnt < c89) begin
// if (data_cnt < 3) begin
// clk_out_ache <= 1'b1;
// end
if(data_cnt == 0||
data_cnt == 4||
data_cnt == 8||
data_cnt == 12||
data_cnt == 16||
data_cnt == 20) begin
clk_out_ache <= ~clk_out_ache;
end
else begin
clk_out_ache <= clk_out_ache;
end
end
else if(data_cnt == 24 ||data_cnt==28 ||
data_cnt == 33 ||data_cnt==37 ||
data_cnt == 42 ||data_cnt==46 ||
data_cnt == 51 ||data_cnt==55 ||
data_cnt == 60 ||data_cnt==64 ||
data_cnt == 69 ||data_cnt==73 ||
data_cnt == 78 ||data_cnt==82
)begin
clk_out_ache <= ~clk_out_ache;
end
else begin
clk_out_ache <= clk_out_ache;
end
end
end
assign clk_out = clk_out_ache;
endmodule
VL42 无占空比要去的奇数分频
`timescale 1ns/1ns
module odd_div (
input wire rst ,
input wire clk_in ,
output wire clk_out5
);
//*************code***********//
reg [ 2:0] data_cnt ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
data_cnt <= 'd0;
end else begin
if(data_cnt == 3'd4) begin
data_cnt <= 3'd0;
end else begin
data_cnt <= data_cnt + 1'd1;
end
end
end
reg clk_out_cache ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
clk_out_cache <= 1'b0;
end
else if (data_cnt == 3'd0 || data_cnt == 3'd2) begin
clk_out_cache <= ~clk_out_cache;
end else begin
clk_out_cache <= clk_out_cache;
end
end
assign clk_out5 = clk_out_cache;
endmodule
VL43 根据状态转移写状态机-三段式
`timescale 1ns/1ns
module fsm1(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
//*************code***********//
parameter s0 = 3'b000;
parameter s1 = 3'b001;
parameter s2 = 3'b010;
parameter s3 = 3'b100;
reg [2:0] st_cur,next_cur;
always @(posedge clk or negedge rst) begin
if (!rst) begin
st_cur <= s0;
end else begin
st_cur <= next_cur;
end
end
always @(*) begin
case (st_cur)
s0:begin
next_cur = (data)?s1:s0;
end
s1: begin
next_cur = (data)?s2:s1;
end
s2: begin
next_cur = (data)?s3:s2;
end
s3: begin
next_cur = (data)?s0:s3;
end
default: next_cur = s0;
endcase
end
always @(posedge clk or negedge rst) begin
if(!rst) begin
flag <= 1'b0;
end else begin
if(st_cur == s3) begin
if (data) begin
flag <= 1'b1;
end
else begin
flag <= 1'b0;
end
end else begin
flag <= 1'b0;
end
end
end
//*************code***********//
endmodule
VL44 根据状态转移写状态机-二段式
`timescale 1ns/1ns
module fsm2(
input wire clk ,
input wire rst ,
input wire data ,
output reg flag
);
//*************code***********//
parameter s0 = 4'b0000;
parameter s1 = 4'b0001;
parameter s2 = 4'b0010;
parameter s3 = 4'b0100;
parameter s4 = 4'b1000;
reg [3:0] st_cur,next_cur;
always @(posedge clk or negedge rst) begin
if (!rst) begin
st_cur <= s0;
end else begin
st_cur <= next_cur;
end
end
always @(*) begin
if(!rst) begin
flag <= 1'b0;
// next_cur = s0;
end
case (st_cur)
s0: begin
next_cur = data?s1:s0;
flag <= 1'b0;
end
s1: begin
next_cur = data?s2:s1;
flag <= 1'b0;
end
s2: begin
next_cur = data?s3:s2;
flag <= 1'b0;
end
s3: begin
next_cur = data?s4:s3;
flag <= 1'b0;
end
s4: begin
next_cur = data?s1:s0;
flag <= 1'b1;
end
default: begin
next_cur = s0;
flag <= 1'b0;
end
endcase
end
//*************code***********//
endmodule
VL45 异步FIFO
`timescale 1ns/1ns
/***************************************RAM*****************************************/
module dual_port_RAM #(
parameter DEPTH = 16 , //ram的存储空间8*16
parameter WIDTH = 8
) (
input wclk ,//写时钟
input wenc ,//写使能
input [$clog2(DEPTH)-1:0]waddr ,//深度对2取对数,得到地址的位宽。
input [WIDTH-1:0] wdata ,//数据写入
input rclk ,//读时钟
input renc ,//读使能
input [$clog2(DEPTH)-1:0]raddr ,//深度对2取对数,得到地址的位宽。
output reg [WIDTH-1:0] rdata //数据输出
);
reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1] ;//开辟存储空间
always @(posedge wclk) begin //写数据
if(wenc)
RAM_MEM[waddr] <= wdata;
end
always @(posedge rclk) begin //读数据
if(renc)
rdata <= RAM_MEM[raddr];
end
endmodule
/***************************************AFIFO*****************************************/
module asyn_fifo#( //8为宽,数据深度为16,则用4位地址可以表示
parameter WIDTH = 8,
parameter DEPTH = 16
)(
input wclk ,//写时钟
input rclk ,//读时钟
input wrstn ,//写时钟域异步复位
input rrstn ,//读时钟域异步复位
input winc ,//写使能
input rinc ,//读使能
input [WIDTH-1:0] wdata ,//写数据
output wire wfull ,//将满标志
output wire rempty ,//将空标志
output wire [WIDTH-1:0] rdata //读出数据
);
localparam ADDR_WIDTH = $clog2(DEPTH); //定义地址宽度
//定义双端口ram的读写地址
wire [ADDR_WIDTH-1:0] wr_adr ;//双端口ram的写地址
wire [ADDR_WIDTH-1:0] rd_adr ;//双端口ram的读地址
reg [ADDR_WIDTH:0] wr_adr_ptr ;//写指针
reg [ADDR_WIDTH:0] rd_adr_ptr ;//读指针
//转换为格雷码进行打拍操作
wire [ADDR_WIDTH:0] wr_adr_gray ;//写地址指针二进制转化为格雷码
reg [ADDR_WIDTH:0] wr_adr_gray1 ;//打一拍缓存
reg [ADDR_WIDTH:0] wr_adr_gray2 ;//打两拍缓存
wire [ADDR_WIDTH:0] rd_adr_gray ;//读地址指针二进制转化为格雷码
reg [ADDR_WIDTH:0] rd_adr_gray1 ;//打一拍缓存
reg [ADDR_WIDTH:0] rd_adr_gray2 ;//打两拍缓存
//读写地址比控制指针少一位
assign wr_adr = wr_adr_ptr[ADDR_WIDTH-1:0];
assign rd_adr = rd_adr_ptr[ADDR_WIDTH-1:0];
//写地址指针控制
always @(posedge wclk or negedge wrstn) begin
if (!wrstn) begin
wr_adr_ptr <= 'd0;
end else begin
if(winc && (~wfull)) begin
wr_adr_ptr <= wr_adr_ptr + 1'b1;
end else begin
wr_adr_ptr <= wr_adr_ptr;
end
end
end
//读地址指针控制
always @(posedge rclk or negedge rrstn) begin
if (!rrstn) begin
rd_adr_ptr <= 'd0;
end else begin
if(rinc && (~rempty)) begin
rd_adr_ptr <= rd_adr_ptr + 1'b1;
end else begin
rd_adr_ptr <= rd_adr_ptr;
end
end
end
//二进制指针转化为格雷码
assign wr_adr_gray = (wr_adr_ptr >> 1) ^ wr_adr_ptr;
assign rd_adr_gray = (rd_adr_ptr >> 1) ^ rd_adr_ptr;
reg [ADDR_WIDTH:0] wr_adr_gray_reg ;//写地址指针二进制转化为格雷码
always @(posedge wclk or negedge wrstn) begin
if (!wrstn) begin
wr_adr_gray_reg <= 'd0;
end else begin
wr_adr_gray_reg <= wr_adr_gray;
end
end
reg [ADDR_WIDTH:0] rd_adr_gray_reg ;//写地址指针二进制转化为格雷码
always @(posedge rclk or negedge rrstn) begin
if (!rrstn) begin
rd_adr_gray_reg <= 'd0;
end else begin
rd_adr_gray_reg <= rd_adr_gray;
end
end
//格雷码的同步 读时钟域同步到写时钟域
always @(posedge wclk or negedge wrstn) begin
if (!wrstn) begin
rd_adr_gray1 <= 'd0;
rd_adr_gray2 <= 'd0;
end else begin
rd_adr_gray1 <= rd_adr_gray_reg;
rd_adr_gray2 <= rd_adr_gray1;
end
end
//格雷码的同步 写时钟域同步到读时钟域
always @(posedge rclk or negedge rrstn) begin
if (!rrstn) begin
wr_adr_gray1 <= 'd0;
wr_adr_gray2 <= 'd0;
end else begin
wr_adr_gray1 <= wr_adr_gray_reg;
wr_adr_gray2 <= wr_adr_gray1;
end
end
assign rempty = (rd_adr_gray_reg == wr_adr_gray2) ? 1'b1 : 1'b0;
assign wfull = (wr_adr_gray_reg[ADDR_WIDTH] != rd_adr_gray2[ADDR_WIDTH]) && (wr_adr_gray[ADDR_WIDTH-1] != rd_adr_gray2[ADDR_WIDTH-1]) && (wr_adr_gray[ADDR_WIDTH-2:0] == rd_adr_gray2[ADDR_WIDTH-2:0]);
dual_port_RAM #(.DEPTH(DEPTH), .WIDTH(WIDTH))
u_dual_port_RAM(
.wclk(wclk),
.rclk(rclk),
.wenc(winc && (~wfull)),
.renc(rinc && (~rempty)),
.waddr(wr_adr),
.raddr(rd_adr),
.wdata(wdata),
.rdata(rdata)
);
endmodule
VL46 同步FIFO
`timescale 1ns/1ns
/******
*******/
/**********************************RAM************************************/
module dual_port_RAM #(parameter DEPTH = 16,
parameter WIDTH = 8 )(
input wclk //写数据时钟
,input wenc //写使能
,input [$clog2(DEPTH)-1:0] waddr //深度对2取对数,得到地址的位宽
,input [WIDTH-1:0] wdata //数据写入
,input rclk //读数据时钟
,input renc //读使能
,input [$clog2(DEPTH)-1:0] raddr //深度对2取对数,得到地址的位宽。
,output reg [WIDTH-1:0] rdata //数据输出
);
reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1] ;//开辟宽度为WIDTH,深度为DEPTH的RAM_MEM
//向RAM_MEM中写入数据,其中waddr写地址
always @(posedge wclk) begin
if(wenc)
RAM_MEM[waddr] <= wdata;
end
//从RAM_MEM读出数据,其中raddr为读地址
always @(posedge rclk) begin
if(renc)
rdata <= RAM_MEM[raddr];
end
endmodule
/**********************************SFIFO************************************/
module sfifo#(
parameter WIDTH = 8 ,//定义宽度
parameter DEPTH = 16 //定义深度
)(
input clk ,//时钟
input rst_n ,//复位
input winc ,//写使能
input rinc ,//读使能
input [WIDTH-1:0] wdata ,//写数据
output reg wfull ,//写满标志
output reg rempty ,//读空标志
output wire [WIDTH-1:0] rdata //读数据
);
localparam ADDR_WIDTH = $clog2(DEPTH) ;
reg [ADDR_WIDTH:0] waddr ;
reg [ADDR_WIDTH:0] raddr ;
//写地址定义
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
waddr <= 'b0;
end else begin
if(winc && ~wfull) begin //如果写使能,而且写未满
waddr <= waddr + 1'b1;
end
else begin
waddr <= waddr;
end
end
end
//读地址定义
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
raddr <= 'b0;
end else begin
if(rinc && ~rempty) begin //如果写使能,而且写未满
raddr <= raddr + 1'b1;
end
else begin
raddr <= raddr;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
wfull <= 'b0;
rempty <= 'b0;
end else begin
wfull <= (raddr == {~waddr[ADDR_WIDTH], waddr[ADDR_WIDTH-1:0]});
rempty <= (raddr == waddr);
end
end
dual_port_RAM #(
.DEPTH(DEPTH),
.WIDTH(WIDTH)
)
dual_port_RAM_U0(
.wclk(clk),
.wenc(winc&&~wfull),
.waddr(waddr[ADDR_WIDTH-1:0]),
.wdata(wdata),
.rclk(clk),
.renc(rinc&&~rempty),
.raddr(raddr[ADDR_WIDTH-1:0]),
.rdata(rdata)
);
endmodule
VL47 格雷码计数器
`timescale 1ns/1ns
module gray_counter(
input clk ,
input rst_n ,
output reg [ 3:0] gray_out
);
reg [ 3:0] binary_cnt ;
reg flag ;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
flag <= 1'd0;
end
else begin
flag <= ~flag;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
binary_cnt <= 1'd0;
end else begin
if (flag == 1'd1) begin
binary_cnt <= binary_cnt + 1'd1;
end else begin
binary_cnt <= binary_cnt;
end
end
end
always @(*) begin
gray_out <= binary_cnt ^ (binary_cnt >> 1);
end
endmodule
VL48 多bit MUX同步器
`timescale 1ns/1ns
module mux(
input clk_a ,
input clk_b ,
input arstn ,
input brstn ,
input [3:0] data_in ,
input data_en ,
output reg [3:0] dataout
);
endmodule
VL49 脉冲同步电路
`timescale 1ns/1ns
module pulse_detect(
input clk_fast ,
input clk_slow ,
input rst_n ,
input data_in ,
output dataout
);
reg src_state ;
reg src_state_d0 ;
reg src_state_d1 ;
reg src_state_d2 ;
//原时钟域下脉冲信号转变为电平信号
always @(posedge clk_fast or negedge rst_n) begin
if(!rst_n)
src_state <= 1'b0;
else
src_state <= data_in ^ src_state; //通过异或门做处理
end
always @(posedge clk_slow or negedge rst_n) begin
if (!rst_n) begin
src_state_d0 <= 1'b0;
src_state_d1 <= 1'b0;
src_state_d2 <= 1'b0;
end else begin
src_state_d0 <= src_state;
src_state_d1 <= src_state_d0;
src_state_d2 <= src_state_d1;
end
end
//边沿检测产生新的脉冲
assign dataout = src_state_d1 ^ src_state_d2;
endmodule
VL50 简易秒表
`timescale 1ns/1ns
module count_module(
input clk ,
input rst_n ,
output reg [ 5:0] second ,
output reg [ 5:0] minute
);
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
second <= 'd0;
//minute <= 'd0;
end else begin
if(second == 6'd60) begin
second <= 1'd1;
end else begin
second <= second + 1'd1;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
minute <= 1'd0;
end else begin
if (second == 6'd60) begin
minute <= minute + 1'd1;
end
if (minute == 6'd60) begin
minute <= 1'd0;
end
end
end
endmodule
VL51 可置位计数器
`timescale 1ns/1ns
module count_module(
input clk ,
input rst_n ,
input set ,
input [ 3:0] set_num ,
output reg [ 3:0] number ,
output reg zero
);
reg [ 3:0] data_cnt ;
//定义计数器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_cnt <= 'd0;
end else begin
if(set == 1'd1) begin
data_cnt <= set_num;
end
data_cnt <= data_cnt + 1'd1;
end
end
//
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
zero <= 1'd0;
end else begin
if (data_cnt == 1'd0) begin
zero <= 1'd1;
end else begin
zero <= 1'd0;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
number <=4'd0;
end else begin
number <= data_cnt;
end
end
endmodule
VL52 加减计数器
`timescale 1ns/1ns
module count_module(
input clk ,
input rst_n ,
input mode ,
output reg [ 3:0] number ,
output reg zero
);
reg [ 3:0] data_cnt ;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_cnt <= 4'd0;
end else begin
if(mode == 1'd1) begin
if(data_cnt == 4'd9) begin
data_cnt <= 1'd0;
end else begin
data_cnt <= data_cnt + 1'd1;
end
end
else if(mode == 1'd0) begin
if (data_cnt == 4'd0) begin
data_cnt <= 4'd9;
end else begin
data_cnt <= data_cnt - 1'd1;
end
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
number <= 4'd0;
end else begin
number <= data_cnt;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
zero <= 1'd0;
end else begin
if(data_cnt == 1'd0) begin
zero <= 1'd1;
end else begin
zero <= 1'd0;
end
end
end
endmodule
VL53 单端口RAM
`timescale 1ns/1ns
module RAM_1port(
input clk ,
input rst ,
input enb ,
input [ 6:0] addr ,
input [ 3:0] w_data ,
output wire [ 3:0] r_data
);
//*************code***********//
reg [3:0] ram_reg [127:0]; //存储宽度为4位,深度为128
reg [ 3:0] r_data_ache ;
integer i;
always @(posedge clk or negedge rst) begin
if(!rst) begin
for (i =0 ; i < 128; i = i + 1) begin
ram_reg[i] <= 4'b0;
end
end else begin
if(enb) begin
ram_reg[addr] <= w_data;
end else begin
ram_reg[addr] <= ram_reg[addr];
end
end
end
assign r_data = enb ? 4'd0 : ram_reg[addr];
//*************code***********//
endmodule
VL54 RAM的简单实现
`timescale 1ns/1ns
module ram_mod(
input clk ,
input rst_n ,
input write_en ,
input [ 7:0] write_addr ,
input [ 3:0] write_data ,
input read_en ,
input [ 7:0] read_addr ,
output reg [ 3:0] read_data
);
reg [3:0] ram_reg [127:0];
integer i;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (i = 0;i<128 ; i = i + 1) begin
ram_reg[i] <= 4'b0;
end
read_data <= 4'd0;
end else begin
if(write_en) begin
ram_reg[write_addr] <= write_data;
end
if(read_en) begin
read_data <= ram_reg[read_addr];
end
end
end
endmodule
VL55 Johnson Counter
`timescale 1ns/1ns
module JC_counter(
input clk ,
input rst_n ,
output reg [ 3:0] Q
);
reg [ 2:0] data_cnt ;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_cnt <= 3'b0;
end else begin
data_cnt <= data_cnt + 1'd1;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
Q <= 4'd0;
end else begin
if (data_cnt <= 4'd3) begin
Q <= (Q>>1) | 1000;
end
else begin
Q <= (Q>>1);
end
end
end
endmodule
VL56 流水线乘法器
`timescale 1ns/1ns
module multi_pipe#(
parameter size = 4
)(
input clk ,
input rst_n ,
input [size-1:0] mul_a ,
input [size-1:0] mul_b ,
output reg [size*2-1:0] mul_out
);
/********************************************************************/
reg [7:0] addr01;
reg [7:0] addr23;
wire [7:0] temp0 ;
wire [7:0] temp1 ;
wire [7:0] temp2 ;
wire [7:0] temp3 ;
assign temp0 = mul_b[0]? {4'b0, mul_a} : 'd0;
assign temp1 = mul_b[1]? {3'b0, mul_a, 1'b0} : 'd0;
assign temp2 = mul_b[2]? {2'b0, mul_a, 2'b0} : 'd0;
assign temp3 = mul_b[3]? {1'b0, mul_a, 3'b0} : 'd0;
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
addr01 <= 'd0;
addr23 <= 'd0;
mul_out <= 'd0;
end
else begin
addr01 <= temp0 + temp1;
addr23 <= temp2 + temp3;
mul_out <= addr01 + addr23;
end
end
endmodule
VL57 交通灯
`timescale 1ns/1ns
module triffic_light
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input pass_request,
output wire[7:0]clock,
output reg red,
output reg yellow,
output reg green
);
endmodule
VL58 游戏机计费程序
`timescale 1ns/1ns
module game_count
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input [9:0]money,
input set,
input boost,
output reg[9:0]remain,
output reg yellow,
output reg red
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
remain <= 'd0;
end else begin
if(set) begin
remain <= money + remain;
end
else if (boost) begin
if (remain < 'd2) begin
remain <= 'd0;
end else begin
remain <= remain - 'd2;
end
end
else if (!boost) begin
if (remain < 'd1) begin
remain <= 'd0;
end
else begin
remain <= remain - 'd1;
end
end
else begin
remain <= remain;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
red <= 1'd0;
end else begin
if(remain < 'd1) begin
red <= 1'd1;
end else begin
red <= 1'd0;
end
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
yellow <= 1'd0;
end else begin
if(yellow < 'd10 && yellow > 'd0) begin
yellow <= 1'd1;
end else begin
yellow <= 1'd0;
end
end
end
endmodule