开发环境:Quartus II 8.1 + Nios II IDE 8.1
外设功能:4*4键盘
自定义外设是SOPC系统灵活性的重要体现,是SOPC系统中极其重要的一种设计方法。在大量的数据需要处理时,利用自定义外设由具体的硬件来实现,可以极大程度的提高系统运行的速度,同时便于系统的模块化与集成,是SOPC系统设计的重中之重!!!
在设计自定义外设之前,一定要知道外围电路的工作原理,也就是自定义的外设的时序、逻辑一定要根据具体的硬件电路来设计。其原图在前一篇Verilog HDL 4*4矩阵 键盘扫描程序中。
键盘是嵌入式系统中应用最广的输入设备,这里要设计的就是4*4键盘的硬件扫描电路,可以通过读相关的寄存器获取键值,值得一提的是该自定义外设支持中断的方式获取键值!!!
自定义外设可以为Master和Slave两种,这里设计的是一个只含有Slave的外设,Verilog HDL源程序如下,主要是在上一篇文章的基础上修改而来。主要添加了Avalon Slave Port的接口部分:也就是和Avalon交换架构进行交互的一些信号的集合(这只是最基本的传输,不包含任何高级传输属性)。
2 module key
3 (
4 //Avalon MM slave port interface "s1" with irq
5 clk, //50MHZ
6 reset_n,
7
8 chipselect,
9 address,
10 write,
11 writedata,
12 readdata,
13 irq,
14 row,
15 col
16 );
17 input clk;
18 input reset_n;
19
20 input chipselect;
21 input [1:0] address;
22 input write;
23 input [7:0] writedata;
24 output [7:0] readdata;
25 input [3:0] row;
26 output irq;
27 output [3:0] col;
28
29 reg [7:0] readdata;
30 reg irq;
31 reg irq_reg;
32 reg [3:0] col;
33 reg [4:0] key_value;
34
35 reg [12:0] count;//delay
36 reg [2:0] state;
37 reg [2:0] pre_state;
38 reg key_flag;
39 reg [3:0] col_reg;
40 reg [3:0] row_reg;
41 wire [7:0] irq_capture;
42 wire [7:0] readdata_reg;
43
44 assign readdata_reg={8{(address==0)}}&{4'b0000,key_value}|
45 ({8 {(address == 1)}} & irq_capture);
46
47 assign irq_capture=key_value;
48
49 always @(posedge clk)
50 if(!reset_n) begin readdata<=8'h00;irq<=1'b0;end
51 else
52 begin
53 readdata<=readdata_reg;
54 if(chipselect&write&&(address==2)) irq<=1'b0;//clear irq signal
55 else if(key_flag==1'b1) irq<=1;
56 end
57
58
59 always @(posedge clk or negedge reset_n)
60 if(!reset_n) begin col<=4'b0000;state<=0;pre_state<=0;count<=0;end
61 else
62 begin
63 case (state)
64 0:
65 begin
66 col[3:0]<=4'b0000;
67 key_flag<=1'b0;
68 pre_state<=0;
69 if(row[3:0]!=4'b1111) state<=2;
70 else begin state<=0;end
71 end
72 1:
73 begin
74 if(count<5000) begin count<=count+1;state<=1;end
75 else
76 begin
77 count<=0;
78 if(row[3:0]!=4'b1111) state<=6;
79 else state<=pre_state+1;
80 end
81 end
82
83 2:
84 begin
85 col[3:0]<=4'b1110;
86 state<=1;
87 pre_state<=2;
88 end
89 3:
90 begin
91 col[3:0]<=4'b1101;
92 state<=1;
93 pre_state<=3;
94 end
95 4:
96 begin
97 col[3:0]<=4'b1011;
98 state<=1;
99 pre_state<=4;
100 end
101 5:
102 begin
103 col[3:0]<=4'b0111;
104 state<=1;
105 pre_state<=5;
106 end
107
108 6:
109 begin
110 if(row[3:0]!=4'b1111)
111 begin
112 col_reg<=col;
113 row_reg<=row;
114 state<=7;
115 key_flag<=1'b1;
116 end
117 else
118 begin state<=0;end
119 end
120 7:
121 begin
122 key_flag<=1'b0;
123 if(row[3:0]!=4'b1111) state<=7;
124 else state<=0;
125 end
126 endcase
127 end
128
129
130 always @(clk or col_reg or row_reg)
131 begin
132 if(!reset_n) key_value<=0;
133 else
134 if(key_flag==1'b1)
135 begin
136 case ({col_reg,row_reg})
137 8'b1110_1110:key_value<=1;
138 8'b1110_1101:key_value<=2;
139 8'b1110_1011:key_value<=3;
140 8'b1110_0111:key_value<=4;
141
142 8'b1101_1110:key_value<=5;
143 8'b1101_1101:key_value<=6;
144 8'b1101_1011:key_value<=7;
145 8'b1101_0111:key_value<=8;
146
147 8'b1011_1110:key_value<=9;
148 8'b1011_1101:key_value<=10;
149 8'b1011_1011:key_value<=11;
150 8'b1011_0111:key_value<=12;
151
152 8'b0111_1110:key_value<=13;
153 8'b0111_1101:key_value<=14;
154 8'b0111_1011:key_value<=15;
155 8'b0111_0111:key_value<=16;
156 endcase
157 end
158 end
159 endmodule
160
下面介绍如何将自定义外设添加到SOPC系统。
打开SOPC Builder,添加Verilog HDL文件。如下图:
设置信号类型如下:
设置Avalon接口如下:
添加自定义组件的一些基本信息:
这样就完成了自定义组件的添加,保存后退出即可在SOPC Builder 组件栏看到刚添加的组件。
点“Add”即可像添加其它IP一样添加到SOPC系统中来。
可以清楚的看到键盘中断优先级为“2”,Nios II系统中断号越低,中断优先级越高。点击“Generate”生成Nios II系统如下,可以看到组件已经成功添加到顶层文件.
绑定管脚后编译,即完成了自定义外设的整个硬件设计,接下来就是软件设计与验证。