线性序列机结构
线性序列机的好处是在每个时刻做的事情都是已知的
ADC测试(top)
module ADC128S102_test(
clk,
rst_n,
key,
led,
addr,
ADC_SCLK,
ADC_CS_N,
ADC_DIN,
ADC_DOUT,
DIO,
SRCLK,
RCLK
);
input clk;
input rst_n;
input key;
output reg led;
input [2:0]addr;
output ADC_SCLK;
output ADC_CS_N;
output ADC_DIN;
input ADC_DOUT;
output DIO;
output SRCLK;
output RCLK;
wire [11:0]data;
wire conv_done;
wire conv_go;
wire Key_P_Flag;
wire [31:0] disp_data;
wire [3:0]ge;
wire [3:0]shi;
wire [3:0]bai;
wire [3:0]qian;
assign ge=data%10;//个
assign shi=data/10%10;//十
assign bai=data/100%10;//百
assign qian=data/1000;//千
assign disp_data={20'd0,qian,bai,shi,ge};
assign conv_go=Key_P_Flag;
key_filter key_filter(
.Clk(clk),
.Rst_n(rst_n),
.key_in(key),
.key_flag(Key_P_Flag),
.key_state()
);
ADC128S102_Driver ADC128S102_Driver(
.clk(clk),
.rst_n(rst_n),
.conv_go(conv_go),
.addr(addr),
.conv_done(conv_done),
.data(data),
.ADC_SCLK(ADC_SCLK),
.ADC_CS_N(ADC_CS_N),
.ADC_DIN(ADC_DIN),
.ADC_DOUT(ADC_DOUT)
);
hex8_hc595_test hex8_hc595_test(
.clk(clk),
.rst_n(rst_n),
.data(disp_data),
.DIO(DIO),
.SRCLK(SRCLK),
.RCLK(RCLK)
);
always@(posedge clk or negedge rst_n)
if(!rst_n)
led<=0;
else if(conv_done)
led<=~led;
endmodule
ADC驱动
module ADC128S102_Driver(
clk,
rst_n,
conv_go,
addr,
conv_done,
data,
ADC_SCLK,
ADC_CS_N,
ADC_DIN,
ADC_DOUT
);
input clk;
input rst_n;
input conv_go;
input [2:0]addr;
output reg conv_done;
output reg[11:0] data;
output reg ADC_SCLK;
output reg ADC_CS_N;
output reg ADC_DIN;
input ADC_DOUT;
parameter CLOCK_FREQ=50_000_000;
parameter SCLK_FREQ=12_500_000;
parameter MCNT_DIV_CNT=CLOCK_FREQ/(SCLK_FREQ*2)-1;
reg conv_en;
reg [5:0]lsm_cnt;//序列计数器(LSM:线性序列机)
reg [11:0] data_r;//序列机的执行单元
reg[2:0] r_addr;
reg [7:0]div_cnt;//最小时间单位计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
div_cnt<=0;
else if(conv_en)begin
if(div_cnt==MCNT_DIV_CNT)
div_cnt<=0;
else
div_cnt<=div_cnt+1'd1;
end
else
div_cnt<=0;
end
// reg [5:0]lsm_cnt;//序列计数器(LSM:线性序列机)
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
lsm_cnt<=0;
else if(div_cnt==MCNT_DIV_CNT)begin
if(lsm_cnt==34)
lsm_cnt<=0;
else
lsm_cnt<=lsm_cnt+1'd1;
end
else
lsm_cnt<=lsm_cnt;
end
// reg [11:0] data_r;//序列机的执行单元
// reg[2:0] r_addr;
always@(posedge clk)
if(conv_go)
r_addr<=addr;
else
r_addr<=r_addr;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data_r<=12'd0;
ADC_SCLK<=1'd1;
ADC_DIN<=1'd1;
ADC_CS_N<=1'd1;
end
else if (div_cnt==MCNT_DIV_CNT)begin
case(lsm_cnt)
0:begin ADC_CS_N<=1'd1;ADC_SCLK<=1'd1;end
1:begin ADC_CS_N<=1'd0; end
2:begin ADC_SCLK<=1'd0; end
3:begin ADC_SCLK<=1'd1; end
4:begin ADC_SCLK<=1'd0; end
5:begin ADC_SCLK<=1'd1; end
6:begin ADC_SCLK<=1'd0;ADC_DIN<=r_addr[2]; end
7:begin ADC_SCLK<=1'd1; end
8:begin ADC_SCLK<=1'd0;ADC_DIN<=r_addr[1]; end
9:begin ADC_SCLK<=1'd1; end
10:begin ADC_SCLK<=1'd0;ADC_DIN<=addr[0]; end
11:begin ADC_SCLK<=1'd1;data_r[11]<=ADC_DOUT; end
12:begin ADC_SCLK<=1'd0; end
13:begin ADC_SCLK<=1'd1;data_r[10]<=ADC_DOUT; end
14:begin ADC_SCLK<=1'd0; end
15:begin ADC_SCLK<=1'd1;data_r[9]<=ADC_DOUT; end
16:begin ADC_SCLK<=1'd0; end
17:begin ADC_SCLK<=1'd1;data_r[8]<=ADC_DOUT; end
18:begin ADC_SCLK<=1'd0; end
19:begin ADC_SCLK<=1'd1;data_r[7]<=ADC_DOUT; end
20:begin ADC_SCLK<=1'd0; end
21:begin ADC_SCLK<=1'd1;data_r[6]<=ADC_DOUT; end
22:begin ADC_SCLK<=1'd0; end
23:begin ADC_SCLK<=1'd1;data_r[5]<=ADC_DOUT; end
24:begin ADC_SCLK<=1'd0; end
25:begin ADC_SCLK<=1'd1;data_r[4]<=ADC_DOUT; end
26:begin ADC_SCLK<=1'd0; end
27:begin ADC_SCLK<=1'd1;data_r[3]<=ADC_DOUT; end
28:begin ADC_SCLK<=1'd0; end
29:begin ADC_SCLK<=1'd1;data_r[2]<=ADC_DOUT; end
30:begin ADC_SCLK<=1'd0; end
31:begin ADC_SCLK<=1'd1;data_r[1]<=ADC_DOUT; end
32:begin ADC_SCLK<=1'd0; end
33:begin ADC_SCLK<=1'd1;data_r[0]<=ADC_DOUT; end
34:begin ADC_CS_N<=1'd1; end
default:begin ADC_CS_N<=1'd1; end
endcase
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
data<=0;
conv_done<=0;
end
else if(lsm_cnt==34 && div_cnt==MCNT_DIV_CNT)begin
conv_done<=1;
data<=data_r;
end
else begin
data<=data;
conv_done<=0;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
conv_en<=0;
else if(conv_go)
conv_en<=1;
else if(lsm_cnt==34 && div_cnt==MCNT_DIV_CNT)
conv_en<=0;
else
conv_en<=conv_en;
end
endmodule
74HC595驱动
module HC595_driver(clk,rst_n,seg,sel,DIO,SRCLK,RCLK);
input clk;
input rst_n;
input [7:0]seg;
input [7:0]sel;
output reg DIO;//数据
output reg SRCLK;//时钟
output reg RCLK;//锁存
reg [2:0]div_cnt;
reg [4:0]cnt;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
div_cnt<=0;
cnt<=0;
end
else if(div_cnt==5)begin
div_cnt<=0;
cnt<=cnt+1;
end
else begin
div_cnt<=div_cnt+1;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
DIO<=0;
RCLK<=0;
SRCLK<=0;
end
else begin
case(cnt)
0:begin DIO<=seg[7];SRCLK<=0; RCLK<=1;end
1:begin SRCLK<=1;RCLK<=0; end
2:begin DIO<=seg[6];SRCLK<=0; end
3:begin SRCLK<=1; end
4:begin DIO<=seg[5];SRCLK<=0; end
5:begin SRCLK<=1; end
6:begin DIO<=seg[4];SRCLK<=0; end
7:begin SRCLK<=1; end
8:begin DIO<=seg[3];SRCLK<=0; end
9:begin SRCLK<=1; end
10:begin DIO<=seg[2];SRCLK<=0;end
11:begin SRCLK<=1; end
12:begin DIO<=seg[1];SRCLK<=0;end
13:begin SRCLK<=1; end
14:begin DIO<=seg[0];SRCLK<=0;end
15:begin SRCLK<=1; end
16:begin DIO<=sel[7];SRCLK<=0;end
17:begin SRCLK<=1; end
18:begin DIO<=sel[6];SRCLK<=0;end
19:begin SRCLK<=1; end
20:begin DIO<=sel[5];SRCLK<=0;end
21:begin SRCLK<=1; end
22:begin DIO<=sel[4];SRCLK<=0;end
23:begin SRCLK<=1; end
24:begin DIO<=sel[3];SRCLK<=0;end
25:begin SRCLK<=1; end
26:begin DIO<=sel[2];SRCLK<=0;end
27:begin SRCLK<=1; end
28:begin DIO<=sel[1];SRCLK<=0;end
29:begin SRCLK<=1; end
30:begin DIO<=sel[0];SRCLK<=0;end
31:begin SRCLK<=1; end
endcase
end
end
endmodule
数码管动态扫描
module seg(clk,rst_n,data,sel,seg);//hex
input clk;
input rst_n;
input [31:0]data;
output reg[7:0]sel;//位选
output reg[7:0]seg;//段选
reg [15:0] cnt_1ms;
reg clk_1ms;
reg [2:0]sel_cnt;
reg [3:0]data_temp;
always @(posedge clk or negedge rst_n) begin//1ms分频
if(!rst_n)begin
cnt_1ms<=0;
clk_1ms<=0;
end
else begin
if(cnt_1ms==50000/2-1)begin
cnt_1ms<=0;
clk_1ms<=~clk_1ms;
end
else begin
cnt_1ms<=cnt_1ms+1;
end
end
end
always @(posedge clk_1ms or negedge rst_n) begin//1ms计时
if(!rst_n)begin
sel_cnt<=0;
end
else begin
if(sel_cnt==8)begin
sel_cnt<=0;
end
else begin
sel_cnt<=sel_cnt+1;
end
end
end
always @(posedge clk_1ms) begin//动态扫描
case(sel_cnt)
0:begin sel<=8'b0000_0001;data_temp<=data[3:0];end
1:begin sel<=8'b0000_0010;data_temp<=data[7:4];end
2:begin sel<=8'b0000_0100;data_temp<=data[11:8];end
3:begin sel<=8'b0000_1000;data_temp<=data[15:12];end
4:begin sel<=8'b0001_0000;data_temp<=data[19:16];end
5:begin sel<=8'b0010_0000;data_temp<=data[23:20];end
6:begin sel<=8'b0100_0000;data_temp<=data[27:24];end
7:begin sel<=8'b1000_0000;data_temp<=data[31:28];end
endcase
end
always @(posedge clk_1ms or negedge rst_n) begin
case(data_temp)
0:seg<=8'b1100_0000;//0
1:seg<=8'b1111_1001;//1
2:seg<=8'b1010_0100;//2
3:seg<=8'b1011_0000;//3
4:seg<=8'b1001_1001;//4
5:seg<=8'b1001_0010;//5
6:seg<=8'b1000_0010;//6
7:seg<=8'b1111_1000;//7
8:seg<=8'b1000_0000;//8
9:seg<=8'b1001_0000;//9
10:seg<=8'b1000_1000;//a
11:seg<=8'b1000_0011;//b
12:seg<=8'b1100_0110;//c
13:seg<=8'b1010_0001;//d
14:seg<=8'b1000_0110;//e
15:seg<=8'b1000_1110;//f
endcase
end
endmodule
74HC595驱动数码管通用测试代码
module hex8_hc595_test(clk,rst_n,data,DIO,SRCLK,RCLK);
input clk;
input rst_n;
input [31:0]data;
output DIO,SRCLK,RCLK;
wire [7:0]sel;
wire [7:0]seg;
seg seg0(
.clk(clk),
.rst_n(rst_n),
.data(data),
.sel(sel),
.seg(seg)
);
HC595_driver HC595_driver0(
.clk(clk),
.rst_n(rst_n),
.seg(seg),
.sel(sel),
.DIO(DIO),
.SRCLK(SRCLK),
.RCLK(RCLK)
);
endmodule
按键消抖模块
module key_filter(Clk,Rst_n,key_in,key_flag,key_state);
input Clk;
input Rst_n;
input key_in;
output reg key_flag;
output reg key_state;
localparam
IDEL = 4'b0001,
FILTER0 = 4'b0010,
DOWN = 4'b0100,
FILTER1 = 4'b1000;
reg [3:0]state;
reg [19:0]cnt;
reg en_cnt; //使能计数寄存器
//对外部输入的异步信号进行同步处理
reg key_in_sa,key_in_sb;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
key_in_sa <= 1'b0;
key_in_sb <= 1'b0;
end
else begin
key_in_sa <= key_in;
key_in_sb <= key_in_sa;
end
reg key_tmpa,key_tmpb;
wire pedge,nedge;
reg cnt_full;//计数满标志信号
//使用D触发器存储两个相邻时钟上升沿时外部输入信号(已经同步到系统时钟域中)的电平状态
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
key_tmpa <= 1'b0;
key_tmpb <= 1'b0;
end
else begin
key_tmpa <= key_in_sb;
key_tmpb <= key_tmpa;
end
//产生跳变沿信号
assign nedge = !key_tmpa & key_tmpb;
assign pedge = key_tmpa & (!key_tmpb);
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
en_cnt <= 1'b0;
state <= IDEL;
key_flag <= 1'b0;
key_state <= 1'b1;
end
else begin
case(state)
IDEL :
begin
key_flag <= 1'b0;
if(nedge)begin
state <= FILTER0;
en_cnt <= 1'b1;
end
else
state <= IDEL;
end
FILTER0:
if(cnt_full)begin
key_flag <= 1'b1;
key_state <= 1'b0;
en_cnt <= 1'b0;
state <= DOWN;
end
else if(pedge)begin
state <= IDEL;
en_cnt <= 1'b0;
end
else
state <= FILTER0;
DOWN:
begin
key_flag <= 1'b0;
if(pedge)begin
state <= FILTER1;
en_cnt <= 1'b1;
end
else
state <= DOWN;
end
FILTER1:
if(cnt_full)begin
key_flag <= 1'b1;
key_state <= 1'b1;
en_cnt <= 1'b0;
state <= IDEL;
end
else if(nedge)begin
en_cnt <= 1'b0;
state <= DOWN;
end
else
state <= FILTER1;
default:
begin
state <= IDEL;
en_cnt <= 1'b0;
key_flag <= 1'b0;
key_state <= 1'b1;
end
endcase
end
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 20'd0;
else if(en_cnt)
cnt <= cnt + 1'b1;
else
cnt <= 20'd0;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt_full <= 1'b0;
else if(cnt == 999_999)
cnt_full <= 1'b1;
else
cnt_full <= 1'b0;
endmodule
按下按键,则数码管显示对应的采样数值
本文章使用limfx的vscode插件快速发布