写一个简单的Avalon_MM Slave IP,
供初学者学习.
[描述]
控制七段数码管显示,动态扫描,
每组4个数码管,共用数据线,一共两组.
[程序]
// seven-seg led
// James 2009.08.05
module sevenled( clk,rst_n,
write,writedata,address,
seg_com,seg_led0,seg_led1
);
// for Avalon clock interface
input clk,rst_n;
// for Avalon-MM slave port
input write;
input [7:0] writedata;
input [2:0] address;
// for User port
output [7:0] seg_led0;
output [7:0] seg_led1;
output [7:0] seg_com;
reg [7:0] seg_led0;
reg [7:0] seg_led1;
reg [7:0] seg_com;
reg [7:0] displaydata;
// write regs
reg [7:0] avalon_data[7:0]; //8 regs[7:0]
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
avalon_data[0] <=8'h00;
avalon_data[1] <=8'h00;
avalon_data[2] <=8'h00;
avalon_data[3] <=8'h00;
avalon_data[4] <=8'h00;
avalon_data[5] <=8'h00;
avalon_data[6] <=8'h00;
avalon_data[7] <=8'h00;
end
else if(write) //IOWR send the write signal automatically
avalon_data[address] <= writedata;
// counter++
reg [15:0] count;
always @(posedge clk or negedge rst_n)
if(!rst_n)
count <= 16'h0;
else
count <= count + 1'b1;
// scan dynamically and CS
always @(count[14:12]) //82us的扫描速度,大一些也可以
begin
case(count[14:12])
3'b000: begin
displaydata = avalon_data[0];
seg_com = 8'h01;
end
3'b001: begin
displaydata = avalon_data[1];
seg_com = 8'h02;
end
3'b010: begin
displaydata = avalon_data[2];
seg_com = 8'h04;
end
3'b011: begin
displaydata = avalon_data[3];
seg_com = 8'h08;
end
3'b100: begin
displaydata = avalon_data[4];
seg_com = 8'h10;
end
3'b101: begin
displaydata = avalon_data[5];
seg_com = 8'h20;
end
3'b110: begin
displaydata = avalon_data[6];
seg_com = 8'h40;
end
3'b111: begin
displaydata = avalon_data[7];
seg_com = 8'h80;
end
default: seg_com = 8'h00;
endcase
end
// Segment Select LED0
always @(seg_com[3:0])
case(displaydata)
4'h1: seg_led0 = 8'h06; // 1
4'h2: seg_led0 = 8'h5b; // 2
4'h3: seg_led0 = 8'h4f; // 3
4'h4: seg_led0 = 8'h66; // 4
4'h5: seg_led0 = 8'h6d; // 5
4'h6: seg_led0 = 8'h7d; // 6
4'h7: seg_led0 = 8'h07; // 7
4'h8: seg_led0 = 8'h7f; // 8
4'h9: seg_led0 = 8'h6f; // 9
4'ha: seg_led0 = 8'h77; // A
4'hb: seg_led0 = 8'h7c; // b
4'hc: seg_led0 = 8'h39; // c
4'hd: seg_led0 = 8'h5e; // d
4'he: seg_led0 = 8'h79; // E
4'hf: seg_led0 = 8'h71; // F
4'h0: seg_led0 = 8'h3f; // 0
default : seg_led0 = 8'h00;
endcase
// Segment Select LED1
always @(seg_com[7:4])
case(displaydata)
4'h1: seg_led1 = 8'h06;
4'h2: seg_led1 = 8'h5b;
4'h3: seg_led1 = 8'h4f;
4'h4: seg_led1 = 8'h66;
4'h5: seg_led1 = 8'h6d;
4'h6: seg_led1 = 8'h7d;
4'h7: seg_led1 = 8'h07;
4'h8: seg_led1 = 8'h7f;
4'h9: seg_led1 = 8'h6f;
4'ha: seg_led1 = 8'h77;
4'hb: seg_led1 = 8'h7c;
4'hc: seg_led1 = 8'h39;
4'hd: seg_led1 = 8'h5e;
4'he: seg_led1 = 8'h79;
4'hf: seg_led1 = 8'h71;
4'h0: seg_led1 = 8'h3f;
default : seg_led1 = 8'h00;
endcase
endmodule
[添加]
在SopcBuilder下面,New Component…
Signals界面设置如下,
interface下面设置,
把没有用的删掉
最后一步,选择添加到哪个类别下面,如果有Parameter,可以选择哪些是可以设置的.
finish完成.
双击添加后,自动和MM-Master连起来,一般就一个Master即Nios.
编译即可.
[控制]
在IDE下,用C控制,代码这样即可.
IOWR_8DIRECT(SEVENLED_BASE, 0 , 0x01);
IOWR_8DIRECT(SEVENLED_BASE, 1 , 0x02);
IOWR_8DIRECT(SEVENLED _BASE, 4 , 0x05);
IOWR_8DIRECT(SEVENLED _BASE, 5 , 0x06);
即第一个数码管显示1,第二个显示2;
第五个数码管(第二组的第一个)显示5,第六个显示6.
[完成]
直接给对应寄存器值即可,8个寄存器,对应8个数码管.
硬件完成动态扫描,解放软件的工作.
这样用起来很方便,避免软件上用while或是定时器动态扫描数码管.
尽管简单,但体现了软,硬件协同设计的灵活性.
程序放这了
有错误的地方还请大家指教
文章评论(0条评论)
登录后参与讨论