issp调试数码管显示

项目名称

issp数码管显示

具体要求

对数码管驱动电路进行设计,并利用In system sources and probes editor(ISSP)输入显示的数据,在数码管上正常显示

设计说明

本设计采用的是8位8段的数码管(8位代表8个数码管),每个数码管的结构图如下,下图为共阳极数码管,共阴极与共阳极数码管的的区别在于,公共端是接到高电平还是低电平。数码管的那个段需要点亮时,只需要给所对应的段给低电平例如如果要显示数字0,只需将a、b、c、d、e、f置0,其他段置1即可。

                           

数码管可以显示0-F, 共阳极数码管显示的译码格式如下。

显示的内容        段码(二进制)    段码(16进制)
abcdefgh
0000000118'hc0
1100111118'hf9
2001001018'ha4
3000011018'hb0
4100110018'h99
5010010018'h92
6010000018'h82
7000111118'hf8
8000000018'h80
9000010018'h90
a000100018'h88
b110000018'h83
c011000118'hc6
d100001018'ha1
e011000018'h86
f011100018'h8e

       一般为了节约IO口的资源,数码管 的段选一般接在一起,如果要点亮第一个和第三个数码管,只需要将所对应的位选打开,根据要显示的内容打开段选,但是如果说要同时只显示第一个码管的a段和第二个数码管的b段就没办法实现,因为打开位选之后,打开a段之后,第二个数码管的a段也是打开的。所以就要利用人眼的视觉暂留效果,可以让第一个数码管显示a段,等待1ms之后再显示第二个数码管的b段,在人眼睛看到的是同时显示的。

数码管驱动模块设计架构

cnt产生1ms的标志信号,每个1ms到来改变一次数码管的位选,进行移位。 data_in为数码管输入的内容,经过位选之后,输出选择的数码管的内容,数码管的内容经过lut进行译码转化为16进制显示。

           

由于本次输出的seg和sel采用两块8位74HC595芯片串转并进行输出,节约IO资源。将两块芯片看成一个模块,则为16位的串转并进行输出。ds是数据端口串行数据输入,shcp为移位寄存器的时钟输入,stcp存储寄存器时钟输入。

下图为部分时序图,当shcp为时钟下降沿时,输入数据的最高位,数据最高位最终从第二个移位寄存器进行输出到段选所以输入数据的组成为{seg,sel}, ds在每个shcp的下降沿进行输入数据,上升沿时数据保持不变,由于总共要输入16位数据,所以需要16个下降沿,待16位数据全部输入后,再来一个时钟上升沿数据并行输出。

具体的设计过程是 ,所需要的shcp的时钟设置为12.5MHz,所以先生成12.5M的时钟,由于每个下降沿需要对数据进行输入,上升沿保持不变。设计一个边沿检测电路对shcp的上升沿和下降沿进行检测 ,需要检测到32个,因为从0-31计数进行数据输入,开始计数的时候是从下降沿开始计数,在计数31时刚好也是一个下降沿,下一个上升沿 stcp输出一个高电平,数据进行并行输出  。

           

       这里要注意的是第一次计数是从下降沿开始计数,之后是来一个下降沿或者上升沿计数器加一,这里笔者采用状态机来实现,可能还有更多的方法,但是笔者习惯使用状态机,因为百分之90的逻辑都可以用状态机来实现。这里普通的计数器没办法实现,第一个状态先检查下降沿,检测到之后,跳转状态2计数器加1,检测到有上升沿或者下降沿并且未计满32,计数器加1,  如果没有检测到上升沿或者下降沿继续等待,如果检测到了,并且计满32返回状态1。

                                        

生成issp的ip核

这里没有用到probe,将它的位宽设置为0,将源位宽(数据输入)定义为32,创建好ip核之后,ctrl+o快捷键可以快速打开文件。

     

代码设计

顶层模块设计

module sel_seg_top(
	input	clk,
	input	rst_n,
	output	shcp,
	output	stcp,
	output	ds
);
wire [31:0] data_in;
issp  issp(
	.probe(),
	.source(data_in)
);

wire [7:0] sel;
wire [7:0] seg;
sel_seg sel_seg(
	.clk(clk),
	.rst_n(rst_n),
	.data_in(data_in),
	.sel(sel),
	.seg(seg)
);
hc595  hc595(
	.clk(clk),
	.rst_n(rst_n),
	.data({seg,sel}),
	.shcp(shcp),
	.ds(ds),
	.stcp(stcp)
);

endmodule

 数码管显示模块

module sel_seg(
	input			clk,
	input			rst_n,
	input [31:0]data_in,
	output   [7:0] sel,
	output	reg[7:0]	seg
);

//每1ms改变一下位选

reg [19:0] cnt;
localparam cnt_top=20'd50000;
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		cnt<=0;
	else if(cnt<cnt_top-1)
		cnt<=cnt+1;
	else
		cnt<=0;
wire delay_1ms_done=(cnt==cnt_top-1)?1:0;

//数码管位选移位,每隔1ms改变一个数码管显示

reg [7:0] sel_r;
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		sel_r<=8'b0000_0001;
	else if(delay_1ms_done)begin
		if(sel_r==8'b1000_0000)
			sel_r<=8'b0000_0001;
		else
			sel_r<=sel_r<<1;
	end
	else
		sel_r<=sel_r;
	
选择要显示的数码管
reg [3:0] disp;//显示的数码管
always@(*)
begin
		case(sel_r)
			8'b0000_0001:disp<=data_in[3:0];
			8'b0000_0010:disp<=data_in[7:4];
			8'b0000_0100:disp<=data_in[11:8];
			8'b0000_1000:disp<=data_in[15:12];
			8'b0001_0000:disp<=data_in[19:16];
			8'b0010_0000:disp<=data_in[23:20];
			8'b0100_0000:disp<=data_in[27:24];
			8'b1000_0000:disp<=data_in[31:28];
			default:disp<=0;
		endcase
end
	
//选择的数码管显示的内容
always@(*)
	if(!rst_n)
		seg<=0;
	else begin
		case(disp)
			4'h0:seg<=8'hc0;
			4'h1:seg<=8'hf9;
			4'h2:seg<=8'ha4;
			4'h3:seg<=8'hb0;
			4'h4:seg<=8'h99;
			4'h5:seg<=8'h92;
			4'h6:seg<=8'h82;
			4'h7:seg<=8'hf8;
			4'h8:seg<=8'h80;
			4'h9:seg<=8'h90;
			4'ha:seg<=8'h88;
			4'hb:seg<=8'h83;
			4'hc:seg<=8'hc6;
			4'hd:seg<=8'ha1;
			4'he:seg<=8'h86;
			4'hf:seg<=8'h8e;
			default:seg<=0;
		endcase
	end
	
assign sel=sel_r;
endmodule

位选和段选数据串转并进行输出

module hc595(
	input			clk,
	input			rst_n,
	input	[15:0]data,
	output		shcp,
	output	reg	ds,
	output	reg	stcp
);


//生成12.5M的时钟
reg [3:0] cnt;
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		cnt<=0;
	else if(cnt<3)
		cnt<=cnt+1;
	else
		cnt<=0;
wire shcp_clk=(cnt<2)?1:0;
assign shcp=shcp_clk;

//边沿检测
reg shcp_clk_c1;
reg shcp_clk_c2;
always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		shcp_clk_c1<=0;
		shcp_clk_c2<=0;
	end
	else begin
		shcp_clk_c1<=shcp_clk;
		shcp_clk_c2<=shcp_clk_c1;
	end

wire nedge=shcp_clk_c2  && (~shcp_clk_c1);
wire pedge=shcp_clk_c1  && (~shcp_clk_c2);

//对shcp时钟上升沿和下降沿进行计数,采用状态机进行实现
reg [5:0] shcp_cnt;
reg state;
always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		shcp_cnt<=0;
		state<=0;
	end
	else begin
		case(state)
		0:	begin
				if(nedge)begin
					shcp_cnt<=shcp_cnt+1;
					state<=1;
				end
				else
					state<=0;
			end	
		1:	begin
				if(nedge || pedge)begin
					if(shcp_cnt<32)
						shcp_cnt<=shcp_cnt+1'b1;
					else
						shcp_cnt<=0;
				end
				else
					state<=state;
			end
		default:;
		endcase
	end
//---------------------------------------------//	
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		begin
			stcp<=0;
			ds<=0;
		end
	else
begin
		case(shcp_cnt)
			6'd0	:	begin	ds<=data[15];stcp<=0;	end
			6'd1	:	;	
			6'd2	:	ds<=data[14];
			6'd3	:	;
			6'd4	:	ds<=data[13];	
			6'd5	:	;	
			6'd6	:	ds<=data[12];	
			6'd7	:	;	
			6'd8	:	ds<=data[11];	
			6'd9	:	;	
			6'd10	:	ds<=data[10];	
			6'd11	:	;	
			6'd12	:	ds<=data[9];	
			6'd13	:	;	
			6'd14	:	ds<=data[8];	
			6'd15	:	;	
			6'd16	:	ds<=data[7];	
			6'd17	:	;	
			6'd18	:	ds<=data[6];	
			6'd19	:	;	
			6'd20	:	ds<=data[5];	
			6'd21	:	;	
			6'd22	:	ds<=data[4];	
			6'd23	:	;	
			6'd24	:	ds<=data[3];	
			6'd25	:	;	
			6'd26	:	ds<=data[2];	
			6'd27	:	;	
			6'd28	:	ds<=data[1];	
			6'd29	:	;	
			6'd30	:	ds<=data[0];	
			6'd31	:	;	
			6'd32	:	stcp=1;	
			default:begin	ds<=0;stcp<=0;	end
		endcase
end


		

	
	
endmodule

利用issp进行显示

全编译并配置好代码之后,打开tool->issp,在name中将数据格式改为16进制,随便输入要显示的数据,可以正常显示。

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值