SOPC 8位数码管动态扫描的定制IP
8位数码管的IP,是动态扫描的
//SEG.v
module SEG(clk,reset_n,address,write,writedata,SEG,COM);
input clk;
input reset_n;
input address;
input write;
input [31:0] writedata;
output [7:0] SEG; //共阳极数码管的段码
output [7:0] COM; //位码
reg [31:0] data; //address为0时writedata的寄存器
reg [7:0] SEG;
reg [7:0] COM;
//地址译码
always @ (posedge clk or negedge reset_n)
begin
if(reset_n==1\’b0) data <=8\’b1111_1111;
else if(write && (!address)) data <= writedata;
end
//scan counter
reg[15:0] cnt_scan;
always@(posedge clk or negedge reset_n)
begin
if(!reset_n) cnt_scan<=0;
else cnt_scan<=cnt_scan+1\’b1;
end
reg [3:0] data_buf;//32位writedata,每四位显示一个数码管
//动态扫描
always @(cnt_scan)
begin
case(cnt_scan[15:13])
3\’b000 :begin COM <= 8\’b1111_1110;data_buf=data[3:0];end
3\’b001 :begin COM <= 8\’b1111_1101;data_buf=data[7:4];end
3\’b010 :begin COM <= 8\’b1111_1011;data_buf=data[11:8];end
3\’b011 :begin COM <= 8\’b1111_0111;data_buf=data[15:12];end
3\’b100 :begin COM <= 8\’b1110_1111;data_buf=data[19:16];end
3\’b101 :begin COM <= 8\’b1101_1111;data_buf=data[23:20];end
3\’b110 :begin COM <= 8\’b1011_1111;data_buf=data[27:24];end
3\’b111 :begin COM <= 8\’b0111_1111;data_buf=data[31:28];end
default: COM <= 8\’b1111_1111;
endcase
end
//段码译码
always @(data_buf)
begin
begin
case(data_buf)
8\’h0 : SEG <= 8\’b1100_0000; // 0
8\’h1 : SEG <= 8\’b1111_1001; //1
8\’h2 : SEG <= 8\’b1010_0100; //2
8\’h3 : SEG <= 8\’b1011_0000; //3
8\’h4 : SEG <= 8\’b1001_1001; //4
8\’h5 : SEG <= 8\’b1001_0010; //5
8\’h6 : SEG <= 8\’b1000_0010; //6
8\’h7 : SEG <= 8\’b1111_1000; //7
8\’h8 : SEG <= 8\’b1000_0000; //8
8\’h9 : SEG <= 8\’b1001_0000; //9
8\’ha : SEG <= 8\’b1011_1111; //-
default: SEG <= 8\’b1111_1111;//不显示
endcase
end
end
endmodule
在SOPC的File/New Component 添加SEG.v文件
在signal中将SEG和COM的Interface改为New conduit , Signal type改为export
在点击Finish……
添加CPU NIOS II/s , SDRAM ,Timer 周期设为1s,再添加PLL,CO设为50MHz 相位-75度,C1 50MHz 相位0度,最后添加SEG
pll.c0改名为sd_clk,SDRAM的时钟,pll.c1改名为sys_clk,NIOS 的系统时钟
将CPU,SDRAM,timer和SEG_0的Clock改为sys_clk
将Quartus II工程的BDF中添加刚才建立的SOPC
引脚配置,运行OK后下载到FPGA中
现在我们看软件的编写:
#include <stdio.h>
#include “system.h”
#include “alt_types.h”
#include “sys/alt_irq.h”
#include “altera_avalon_timer_regs.h”
#define seg *(volatile unsigned long *) SEG_0_BASE //数码管IP的基地址
unsigned char second,minute,hour;//秒,分,小时
static void timer_interrupt(void* context,alt_u32 id) //timer 计时1s中断
{
second++;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
hour++;
if(hour==24) hour=0;
}
}
IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_BASE,0);//清楚中断溢出位
}
int main(void) //alt_main()不响应中断,故用main()
{
second=0;
minute=0;
hour=12;
alt_irq_register(TIMER_IRQ,0,timer_interrupt);//中断登记函数
IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_BASE,0);//清楚中断溢出位
IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_BASE,7);//开始计时
while(1)
{
seg = ((hour/10)<<28)+((hour%10)<<24)+(10<<20)+((minute/10)<<16)
+((minute%10)<<12)+(10<<8)+((second/10)<<4)+(second%10); //显示格式 12-00-00
}
return 0;
}