蜗牛

一起交流,共同进步
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

(原创)SOPC系统自定义外设之:硬件设计

Posted on 2009-05-09 19:22  路漫漫...  阅读(4395)  评论(2编辑  收藏  举报
 

开发环境: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交换架构进行交互的一些信号的集合(这只是最基本的传输,不包含任何高级传输属性)。

 

  1 //Write by Nick 2009.5.9
  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<5000begin 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系统如下,可以看到组件已经成功添加到顶层文件.

绑定管脚后编译,即完成了自定义外设的整个硬件设计,接下来就是软件设计与验证。