寄存器设计包括:1.偏移地址,2.寄存器名称,3.各个位的功能,4.读写权限(只读、读写都可以,写后清零)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
一般都有以下寄存器:状态寄存器、控制寄存器,其他寄存器就根据功能而定。
举例如下:
Offset Name Access Bits
31 ... 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
0 Status R/C Busy | Done
4 Read Address R/W Read Address (byte address, 32 bits,
8 N/A N/A
12 Length R/W Length (bytes, 32 bits)
16 N/A N/A
20 N/A N/A
24 Control R/W RCON | 0 | 0 | 0 | I_EN | Go | 0 | Inv | Clr
28 Checksum R Zeros(16) | Checksum result (16 bits)
从端口寄存器包括的模块:
1. 读寄存器模块
2. 写寄存器编写
3. 状态寄存器编写
4. 控制寄存器编写
5. 中断信号编写
6. 模块输出信号
读寄存器模块编写:
临时变量通过一个多路数据选择器获得状态寄存器值,选择条件是从端口地址,然后同步时钟下临时变量赋值给寄存器,最后寄存器赋值给读数据端口。
assign control_readdata_temp = (slave_address == 3'b000)? status_register :
(slave_address == 3'b001)? read_address_register :
(slave_address == 3'b011)? length_register :
(slave_address == 3'b110)? control_register :
(slave_address == 3'b111)? checksum_register : 0;
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
control_readdata_temp_d1 <= 0;
end
else
begin
if (slave_read == 1)
begin
control_readdata_temp_d1 <= control_readdata_temp;/
end
end
end
assign slave_readdata = control_readdata_temp_d1;
写寄存器编写:根据寄存器偏移地址和写信号两个条件,外加字节使能信号。最终把寄存器信号值赋值给wire型变量。
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
XX_register <= 0;
end
else
begin
if ((slave_address == 3'b011) & (slave_write == 1))
begin
if (slave_byteenable[0] == 1)
begin
XX_register[7:0] <= slave_writedata[7:0];
end
if (slave_byteenable[1] == 1)
begin
XX_register[15:8] <= slave_writedata[15:8];
end
if (slave_byteenable[2] == 1)
begin
XX_register[23:16] <= slave_writedata[23:16];
end
if (slave_byteenable[3] == 1)
begin
XX_register[31:24] <= slave_writedata[31:24];
end
end
end
end
assign control_read_XX = XX_register;
状态寄存器编写:
根据输入状态信号和输出状态信号编写对应的状态寄存器位,状态寄存器一般都是进行读操作,也可以加入写清零操作。
always @ (posedge clk or posedge reset)
begin
if (reset)
status_register <= 0;
else
begin
if (done_strobe == 1)
status_register <= 32'h1; // busy and done
else if (control_go == 1)
status_register <= 32'h2; // not busy and not done
else if ((slave_address == 3'b000) & (slave_write == 1))
begin
status_register <= 0; // clear on write
end
end
end
控制寄存器编写:
和一般寄存器一样有写操作部分,最后再根据控制寄存器某一位的状态,确定输出信号。
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
control_register <= 0;
end
else
begin
if ((slave_address == 3'b110) & (slave_write == 1))
begin
if (slave_byteenable[0] == 1)
begin
control_register[7:0] <= slave_writedata[7:0];
end
if (slave_byteenable[1] == 1)
begin
control_register[15:8] <= slave_writedata[15:8];
end
if (slave_byteenable[2] == 1)
begin
control_register[23:16] <= slave_writedata[23:16];
end
if (slave_byteenable[3] == 1)
begin
control_register[31:24] <= slave_writedata[31:24];
end
end
end
end
assign control_fixed_read_address = control_register[8];
assign control_invert = control_register[1];
中断信号编写(中断信号一般在从端口模块中)
中断信号就是多个来自不同寄存器(尤其是状态寄存器和控制寄存器)位信号的组合逻辑值,注意中断信号要可以清空:
assign control_irq = status_register[0] & control_register[4];
Avalon总线信号:要通过同步时钟锁存到寄存器中。
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
slave_write_d1 <= 0;
slave_address_d1 <= 0;
slave_byteenable_d1 <= 0;
end
else
begin
slave_write_d1 <= slave_write;
slave_address_d1 <= slave_address;
slave_byteenable_d1 <= slave_byteenable;
end
end
模块输出信号:
模块输出信号根据内部寄存器(总线信号寄存器、总线地址寄存器、总线字节使能寄存器、控制寄存器等)确定输出。
assign control_go = (slave_write_d1 == 1) & (slave_address_d1 == 3'b110) & (control_register[3] == 1) & (slave_byteenable_d1[0] == 1);
assign control_clear = (slave_write_d1 == 1) & (slave_address_d1 == 3'b110) & (control_register[0] == 1) & (slave_byteenable_d1[0] == 1);
应网友要求将整理的pdf上传,供学习下载。https://static.assets-stash.eet-china.com/album/old-resources/2010/3/7/6bd3d095-3550-41f4-9864-1753cd09639e.rar
用户180508 2010-3-7 11:03
用户142112 2010-3-6 19:31