准备把de2-115上面的存储器外设都给驱动一下,首先就先从简单的sram开始。 Sram的驱动比较简单,和FPGA内部的ram差不多,只不过不是由时钟来控制读写,而是由控制信号来控制读写,读写都很快,基本上一个时钟就可以读取和写入数据,当然这时钟不能太快,不能超过芯片规定的最小时间。 首先肯定是先看datasheet。 首先看看sram的结构框图。 有20位地址总线,对地址进行译码,得到存储器的单元,然后根据控制电路,判断各个控制信号,从而判定是读还是写操作。读的话,数据线16位就是输出,输出数据。如果是写的话,数据线就是输入,从外部接收数据。 这里数据线高8位和低8位是分开的,因为这里有一个位屏蔽功能,可以屏蔽高8位数据线或者是屏蔽低8位数据线。 具体看芯片的真值表就知道了。 从真值表就可以看出芯片的功能了。 上图是管脚说明。 下面就是关键的时序图了。因为要驱动它的话,是肯定要按照规定的时序来的。 首先是读时序。 考虑通用的方式,即CE和OE来控制。而不是直接将OE和CE使能。 先解读下时序: 在地址数据发送后,要过10ns时间后,但是OE拉低6.5ns时间,并且CE拉低10ns时间,数据数据才是有效数据,当然要读数据的话,需要将OE和CE拉低,同时不要忘记WE要拉高,表示是读数据。 第二次读数据,要10ns之后,所以这个10ns就是读取数据的最小时间,才能发送地址。然后OE和CE要满足上图的保持时间。 总体来说,这个时序图还是很简单的。 然后是写的时序, 这时序图也是很简单的。写时候,OE为高为低都是可以的。 写数据间隔也是10ns,在写控制发出后,数据在5ns后为输入有效,且数据要有6ns的建立时间,保持时间可以为0. 搞定时序图后,就开始进行程序的编写了。。 首先是搞定sram的底层驱动。 首先是信号列表。 从注释可以看出各个信号的作用。 这里采用状态机来进行控制,首先是定义状态 定义了5个状态。看名字就知道是干什么的了。。。 状态机采用二段式设计。 核心代码如下。 大致说明一下。 在idle_state:如果判断start信号有效的话,就跳转到发送地址状态。 在send_address_state:这个状态就是将OE和CE给拉低。然后依据命令是读还是写,进行判断跳转到读还是写状态。 在write_state:保持OE,CE为低,同时拉低WE。然后状态跳转到finish_state。 在read_state:保持OE,CE为低,把sram_data上的数据给读取进来。然后状态跳转到finish_state. 在finish_state:就将finish信号给置1 ,然后状态跳转。 整个状态机设计是很简单的。就是要注意各个信号的时序,满足手册上要求的时序,因为系统时钟很慢,只有50M,周期为20ns,完全满足手册上要求的时序。 用状态机设计很简单,但是也有一个问题就是读写太慢了。。手册上写的是10ns就可以进行一次读写,但是这里设计的需要4个时钟,即80ns才能进行一次读写。 程序在说明一下,关于sram_data的处理,因为这个信号是双向的。 assign sram_data = command ? 16'bz : write_data; 这里使用的是双向口的通用处理方法,使用asignn赋值,因为command为1的时候,操作是读数据,所以这个时候赋值为高阻z,就表明是输入了。为0表示写数据,那么就赋值为write_data,作为输出,输出的值由write_data决定。 下面来对这个模块进行仿真看看。 核心的测试代码: 第一个repeat是写数据,这里就观测写的数据是不是和sram_data的值一样的,这个时候sram_data是作为输出的。 第二个repeat是读数据,这里就观测读的数据是不是和sram_data_reg一样的,这个时候sram_data是作为输入的,而输入的值由sram_data_reg决定的。 对于testbench,最后结束的时候,最好用$stop,暂停仿真,不然仿真就一直继续下去了。。 使用modelsim仿真,因为quartus只能用modelsim仿真。 先观察黄线左边的部分,这部分是写数据。就看写的数据和sram_data是不是一样的,发现是一样的。说明功能正确。 然后观察黄线右边的部分,这部分是读数据。就看读的数据是不是和sram_data_reg一样的。发现sram_data_reg和sram_data值一样,这个肯定是当然的,然后有和read_data一样的。说明功能正确。 然后来看看时序部分: 先看写数据。 这个时钟周期是20ns。 Start为高,表明操作开始。这个时候地址数据已经送出,CE,OE,WE持续20ns的高电平,然后持续40ns的低电平,最后才拉高,是符合写的时序的,而且余量还很多。 在看读数据: Start为高,表明操作开始。这个时候地址数据已经送出,CE,OE持续20ns的高电平,然后拉低,持续40ns的低电平,最后才拉高。也是符合读的时序的,而且余量也很多。 按照仿真的情况来看的话,似乎功能是正确的。那么就写个简单的顶层代码,对sram 驱动。 代码功能也很简单,每隔200ms对sram写一个数据,然后将刚写数据读出来,然后赋值给led。然后sram地址加1,写的数据也加1.
1
[backcolor=rgb(248, 248, 248) !important]2
3
[backcolor=rgb(248, 248, 248) !important]4
5
[backcolor=rgb(248, 248, 248) !important]6
7
[backcolor=rgb(248, 248, 248) !important]8
9
[backcolor=rgb(248, 248, 248) !important]10
11
[backcolor=rgb(248, 248, 248) !important]12
13
[backcolor=rgb(248, 248, 248) !important]14
15
[backcolor=rgb(248, 248, 248) !important]16
17
[backcolor=rgb(248, 248, 248) !important]18
19
[backcolor=rgb(248, 248, 248) !important]20
21
[backcolor=rgb(248, 248, 248) !important]22
23
[backcolor=rgb(248, 248, 248) !important]24
25
[backcolor=rgb(248, 248, 248) !important]26
27
[backcolor=rgb(248, 248, 248) !important]28
29
[backcolor=rgb(248, 248, 248) !important]30
31
[backcolor=rgb(248, 248, 248) !important]32
33
[backcolor=rgb(248, 248, 248) !important]34
35
[backcolor=rgb(248, 248, 248) !important]36
37
[backcolor=rgb(248, 248, 248) !important]38
39
[backcolor=rgb(248, 248, 248) !important]40
41
[backcolor=rgb(248, 248, 248) !important]42
43
[backcolor=rgb(248, 248, 248) !important]44
45
[backcolor=rgb(248, 248, 248) !important]46
47
[backcolor=rgb(248, 248, 248) !important]48
49
[backcolor=rgb(248, 248, 248) !important]50
51
[backcolor=rgb(248, 248, 248) !important]52
53
[backcolor=rgb(248, 248, 248) !important]54
55
[backcolor=rgb(248, 248, 248) !important]56
57
[backcolor=rgb(248, 248, 248) !important]58
59
[backcolor=rgb(248, 248, 248) !important]60
61
[backcolor=rgb(248, 248, 248) !important]62
63
[backcolor=rgb(248, 248, 248) !important]64
65
[backcolor=rgb(248, 248, 248) !important]66
67
[backcolor=rgb(248, 248, 248) !important]68
69
[backcolor=rgb(248, 248, 248) !important]70
71
[backcolor=rgb(248, 248, 248) !important]72
73
[backcolor=rgb(248, 248, 248) !important]74
75
[backcolor=rgb(248, 248, 248) !important]76
77
[backcolor=rgb(248, 248, 248) !important]78
79
[backcolor=rgb(248, 248, 248) !important]80
81
[backcolor=rgb(248, 248, 248) !important]82
83
[backcolor=rgb(248, 248, 248) !important]84
85
[backcolor=rgb(248, 248, 248) !important]86
87
[backcolor=rgb(248, 248, 248) !important]88
89
[backcolor=rgb(248, 248, 248) !important]90
91
[backcolor=rgb(248, 248, 248) !important]92
93
[backcolor=rgb(248, 248, 248) !important]94
95
[backcolor=rgb(248, 248, 248) !important]96
97
[backcolor=rgb(248, 248, 248) !important]98
99
[backcolor=rgb(248, 248, 248) !important]100
101
[backcolor=rgb(248, 248, 248) !important]102
103
[backcolor=rgb(248, 248, 248) !important]104
105
[backcolor=rgb(248, 248, 248) !important]106
107
[backcolor=rgb(248, 248, 248) !important]108
109
[backcolor=rgb(248, 248, 248) !important]110
111
[backcolor=rgb(248, 248, 248) !important]112
113
[backcolor=rgb(248, 248, 248) !important]114
115
[backcolor=rgb(248, 248, 248) !important]116
117
[backcolor=rgb(248, 248, 248) !important]118
119
[backcolor=rgb(248, 248, 248) !important]120
121
[backcolor=rgb(248, 248, 248) !important]122
123
[backcolor=rgb(248, 248, 248) !important]124
125
[backcolor=rgb(248, 248, 248) !important]126
127
[backcolor=rgb(248, 248, 248) !important]128
129
[backcolor=rgb(248, 248, 248) !important]130
131
[backcolor=rgb(248, 248, 248) !important]132
133
[backcolor=rgb(248, 248, 248) !important]134
135
[backcolor=rgb(248, 248, 248) !important]136
137
[backcolor=rgb(248, 248, 248) !important]138
139
[backcolor=rgb(248, 248, 248) !important]140
141
[backcolor=rgb(248, 248, 248) !important]142
143
| module sram_control
[backcolor=rgb(248, 248, 248) !important](
input clk,
[backcolor=rgb(248, 248, 248) !important] input rst_n,
[backcolor=rgb(248, 248, 248) !important] //sram interface
output CE_N,
[backcolor=rgb(248, 248, 248) !important] output OE_N,
output WE_N,
[backcolor=rgb(248, 248, 248) !important] output LB_N,
output UB_N,
[backcolor=rgb(248, 248, 248) !important] output [19:0] sram_address,
inout [15:0] sram_data,
[backcolor=rgb(248, 248, 248) !important]
output [15:0] led,
[backcolor=rgb(248, 248, 248) !important]
output [8:0] led2
[backcolor=rgb(248, 248, 248) !important]);
localparam idle_state = 'd1;
[backcolor=rgb(248, 248, 248) !important]localparam write_state = 'd2;
localparam read_state = 'd4;
[backcolor=rgb(248, 248, 248) !important]localparam finish_state = 'd8;
[backcolor=rgb(248, 248, 248) !important]reg start;
wire finish;
reg command;
wire [1:0] byte_control;
[backcolor=rgb(248, 248, 248) !important]assign byte_control = 2'b00;
[backcolor=rgb(248, 248, 248) !important]wire [19:0] address;
wire [15:0] read_data;
reg [19:0] address_counter;
[backcolor=rgb(248, 248, 248) !important]reg [19:0] address_counter_next;
always@(posedge clk or negedge rst_n) begin
[backcolor=rgb(248, 248, 248) !important] if(!rst_n)
address_counter <= 'd0;
[backcolor=rgb(248, 248, 248) !important] else
address_counter <= address_counter_next;
[backcolor=rgb(248, 248, 248) !important]end
[backcolor=rgb(248, 248, 248) !important]//reg [15:0] write_data_reg;
//reg [15:0] write_data_reg_next;
[backcolor=rgb(248, 248, 248) !important]//always@(posedge clk or negedge rst_n) begin
// if(!rst_n)
[backcolor=rgb(248, 248, 248) !important]// write_data_reg <= 'd0;
// else
[backcolor=rgb(248, 248, 248) !important]// write_data_reg <= write_data_reg_next;
//end
reg [23:0] counter_200ms; // 10000000
[backcolor=rgb(248, 248, 248) !important]localparam counter_200ms_value = 24'd1000_0000;
//localparam counter_200ms_value = 24'd10; //for simula tion
[backcolor=rgb(248, 248, 248) !important]always@(posedge clk or negedge rst_n) begin
if(!rst_n)
[backcolor=rgb(248, 248, 248) !important] counter_200ms <= 'd0;
else if(counter_200ms >= counter_200ms_value)
[backcolor=rgb(248, 248, 248) !important] counter_200ms <= 'd0;
else
[backcolor=rgb(248, 248, 248) !important] counter_200ms <= counter_200ms + 1'b1;
end
reg [3:0] state;
[backcolor=rgb(248, 248, 248) !important]reg [3:0] state_next;
always@(posedge clk or negedge rst_n) begin
[backcolor=rgb(248, 248, 248) !important] if(!rst_n)
state <= idle_state;
[backcolor=rgb(248, 248, 248) !important] else
state <= state_next;
[backcolor=rgb(248, 248, 248) !important]end
[backcolor=rgb(248, 248, 248) !important]always@(*) begin
state_next = state;
[backcolor=rgb(248, 248, 248) !important] address_counter_next = address_counter;
command = 1'b0; //default write
[backcolor=rgb(248, 248, 248) !important] //write_data_reg_next = write_data_reg;
start = 1'b0;
[backcolor=rgb(248, 248, 248) !important] case(state)
idle_state: begin
[backcolor=rgb(248, 248, 248) !important] address_counter_next = 'd0;
//write_data_reg_next = 'd0;
[backcolor=rgb(248, 248, 248) !important] state_next = write_state;
end
[backcolor=rgb(248, 248, 248) !important] write_state: begin
if(finish == 1)
[backcolor=rgb(248, 248, 248) !important] begin
start = 1'b0;
[backcolor=rgb(248, 248, 248) !important] state_next = read_state;
end
[backcolor=rgb(248, 248, 248) !important] else
start = 1;
[backcolor=rgb(248, 248, 248) !important] end
read_state: begin
[backcolor=rgb(248, 248, 248) !important] command = 1'b1; //read
if(finish == 1)
[backcolor=rgb(248, 248, 248) !important] begin
start = 1'b0;
[backcolor=rgb(248, 248, 248) !important] address_counter_next = address_counter + 1'b1;
//write_data_reg_next = write_data_reg + 1'b1;
[backcolor=rgb(248, 248, 248) !important] state_next = finish_state;
end
[backcolor=rgb(248, 248, 248) !important] else
start = 1'b1;
[backcolor=rgb(248, 248, 248) !important] end
finish_state: begin
[backcolor=rgb(248, 248, 248) !important] if(counter_200ms == counter_200ms_value)
state_next = write_state;
[backcolor=rgb(248, 248, 248) !important] end
default:
[backcolor=rgb(248, 248, 248) !important] state_next = idle_state;
endcase
[backcolor=rgb(248, 248, 248) !important]end
[backcolor=rgb(248, 248, 248) !important]assign address = address_counter;
[backcolor=rgb(248, 248, 248) !important]sram sram_inst
(
[backcolor=rgb(248, 248, 248) !important] .clk(clk) , // input clk
.rst_n(rst_n) , // input rst_n
[backcolor=rgb(248, 248, 248) !important] .command(command) , // input command
.address(address) , // input [19:0] address
[backcolor=rgb(248, 248, 248) !important] .byte_control(byte_control) , // input [1:0] byte_control
.write_data(address_counter[15:0]) , // input [15:0] write_data
[backcolor=rgb(248, 248, 248) !important] .read_data(read_data) , // output [15:0] read_data
.start(start) , // input start
[backcolor=rgb(248, 248, 248) !important] .finish(finish) , // output finish
.CE_N(CE_N) , // output CE_N
[backcolor=rgb(248, 248, 248) !important] .OE_N(OE_N) , // output OE_N
.WE_N(WE_N) , // output WE_N
[backcolor=rgb(248, 248, 248) !important] .LB_N(LB_N) , // output LB_N
.UB_N(UB_N) , // output UB_N
[backcolor=rgb(248, 248, 248) !important] .sram_address(sram_address) , // output [19:0] sram_address
.sram_data(sram_data) // inout [15:0] sram_data
[backcolor=rgb(248, 248, 248) !important]);
[backcolor=rgb(248, 248, 248) !important]assign led = read_data;
assign led2 = address_counter[8:0];
endmodul
|
然后分配管脚,编译生成sof文件,下到芯片中,发现,成功驱动了。led按照二进制加1的方式进行亮灭。
最后附上整个sram控制的代码:
1
[backcolor=rgb(248, 248, 248) !important]2
3
[backcolor=rgb(248, 248, 248) !important]4
5
[backcolor=rgb(248, 248, 248) !important]6
7
[backcolor=rgb(248, 248, 248) !important]8
9
[backcolor=rgb(248, 248, 248) !important]10
11
[backcolor=rgb(248, 248, 248) !important]12
13
[backcolor=rgb(248, 248, 248) !important]14
15
[backcolor=rgb(248, 248, 248) !important]16
17
[backcolor=rgb(248, 248, 248) !important]18
19
[backcolor=rgb(248, 248, 248) !important]20
21
[backcolor=rgb(248, 248, 248) !important]22
23
[backcolor=rgb(248, 248, 248) !important]24
25
[backcolor=rgb(248, 248, 248) !important]26
27
[backcolor=rgb(248, 248, 248) !important]28
29
[backcolor=rgb(248, 248, 248) !important]30
31
[backcolor=rgb(248, 248, 248) !important]32
33
[backcolor=rgb(248, 248, 248) !important]34
35
[backcolor=rgb(248, 248, 248) !important]36
37
[backcolor=rgb(248, 248, 248) !important]38
39
[backcolor=rgb(248, 248, 248) !important]40
41
[backcolor=rgb(248, 248, 248) !important]42
43
[backcolor=rgb(248, 248, 248) !important]44
45
[backcolor=rgb(248, 248, 248) !important]46
47
[backcolor=rgb(248, 248, 248) !important]48
49
[backcolor=rgb(248, 248, 248) !important]50
51
[backcolor=rgb(248, 248, 248) !important]52
53
[backcolor=rgb(248, 248, 248) !important]54
55
[backcolor=rgb(248, 248, 248) !important]56
57
[backcolor=rgb(248, 248, 248) !important]58
59
[backcolor=rgb(248, 248, 248) !important]60
61
[backcolor=rgb(248, 248, 248) !important]62
63
[backcolor=rgb(248, 248, 248) !important]64
65
[backcolor=rgb(248, 248, 248) !important]66
67
[backcolor=rgb(248, 248, 248) !important]68
69
[backcolor=rgb(248, 248, 248) !important]70
71
[backcolor=rgb(248, 248, 248) !important]72
73
[backcolor=rgb(248, 248, 248) !important]74
75
[backcolor=rgb(248, 248, 248) !important]76
77
[backcolor=rgb(248, 248, 248) !important]78
79
[backcolor=rgb(248, 248, 248) !important]80
81
[backcolor=rgb(248, 248, 248) !important]82
83
[backcolor=rgb(248, 248, 248) !important]84
85
[backcolor=rgb(248, 248, 248) !important]86
87
[backcolor=rgb(248, 248, 248) !important]88
89
[backcolor=rgb(248, 248, 248) !important]90
91
[backcolor=rgb(248, 248, 248) !important]92
93
[backcolor=rgb(248, 248, 248) !important]94
95
[backcolor=rgb(248, 248, 248) !important]96
97
[backcolor=rgb(248, 248, 248) !important]98
99
[backcolor=rgb(248, 248, 248) !important]100
101
[backcolor=rgb(248, 248, 248) !important]102
103
[backcolor=rgb(248, 248, 248) !important]104
105
[backcolor=rgb(248, 248, 248) !important]106
107
[backcolor=rgb(248, 248, 248) !important]108
109
[backcolor=rgb(248, 248, 248) !important]110
111
| module sram
[backcolor=rgb(248, 248, 248) !important](
input clk, //input 50M clock
[backcolor=rgb(248, 248, 248) !important] input rst_n, //reset signal ,avtive low
[backcolor=rgb(248, 248, 248) !important] input command, //1 read 0 write
input [19:0] address, // address to send sram
[backcolor=rgb(248, 248, 248) !important]
input [1:0] byte_control, //00 all select
[backcolor=rgb(248, 248, 248) !important] //10 selcet low byte
//01 select high byte
[backcolor=rgb(248, 248, 248) !important] //11 select no
input [15:0] write_data, //data to write sram
[backcolor=rgb(248, 248, 248) !important]
output [15:0] read_data, //read data from sram
[backcolor=rgb(248, 248, 248) !important]
input start, //start signal , if 1 ,begin to operate sram
[backcolor=rgb(248, 248, 248) !important] output reg finish, //finish signal, if 1 ,mean operate sram finish
[backcolor=rgb(248, 248, 248) !important] //sram interface
output reg CE_N, //sram Chip Enable
[backcolor=rgb(248, 248, 248) !important] output reg OE_N, //sram Output Enable
output reg WE_N, //sram Write Enable
[backcolor=rgb(248, 248, 248) !important] output LB_N, //sram Lower-byte Control (I/O0-I/O7)
output UB_N, //sram Upper-byte Control (I/O8-I/O15)
[backcolor=rgb(248, 248, 248) !important] output [19:0] sram_address, //sram Address
inout [15:0] sram_data //sram Data Inputs/Outputs
[backcolor=rgb(248, 248, 248) !important]);
localparam idle_state = 'd1;
[backcolor=rgb(248, 248, 248) !important] localparam send_address_state = 'd2;
localparam read_state = 'd4;
[backcolor=rgb(248, 248, 248) !important] localparam write_state = 'd8;
localparam finish_state = 'd16;
[backcolor=rgb(248, 248, 248) !important]
[backcolor=rgb(248, 248, 248) !important] assign {UB_N,LB_N} = byte_control;
assign sram_address = address;
[backcolor=rgb(248, 248, 248) !important]
assign sram_data = command ? 16'bz : write_data;
[backcolor=rgb(248, 248, 248) !important]
reg [4:0] state;
[backcolor=rgb(248, 248, 248) !important] reg [4:0] state_next;
[backcolor=rgb(248, 248, 248) !important] always@(posedge clk or negedge rst_n) begin
if(!rst_n)
[backcolor=rgb(248, 248, 248) !important] state <= idle_state;
else
[backcolor=rgb(248, 248, 248) !important] state <= state_next;
end
[backcolor=rgb(248, 248, 248) !important]
//save the read data from sram
[backcolor=rgb(248, 248, 248) !important] reg [15:0] sram_data_reg;
reg [15:0] sram_data_reg_next;
[backcolor=rgb(248, 248, 248) !important] always@(posedge clk or negedge rst_n) begin
if(!rst_n)
[backcolor=rgb(248, 248, 248) !important] sram_data_reg <= 'd0;
else
[backcolor=rgb(248, 248, 248) !important] sram_data_reg <= sram_data_reg_next;
end
[backcolor=rgb(248, 248, 248) !important]
assign read_data = sram_data_reg;
[backcolor=rgb(248, 248, 248) !important]
always@(*) begin
[backcolor=rgb(248, 248, 248) !important] state_next = state;
sram_data_reg_next = sram_data_reg;
[backcolor=rgb(248, 248, 248) !important] CE_N = 1'b1;
OE_N = 1'b1;
[backcolor=rgb(248, 248, 248) !important] WE_N = 1'b1;
finish = 1'b0;
[backcolor=rgb(248, 248, 248) !important] case(state)
idle_state: begin
[backcolor=rgb(248, 248, 248) !important] if(start)
state_next = send_address_state;
[backcolor=rgb(248, 248, 248) !important] end
send_address_state: begin
[backcolor=rgb(248, 248, 248) !important] OE_N = 1'b0;
CE_N = 1'b0;
[backcolor=rgb(248, 248, 248) !important] if(command == 1) //read
begin
[backcolor=rgb(248, 248, 248) !important] state_next = read_state;
end
[backcolor=rgb(248, 248, 248) !important] else //write
begin
[backcolor=rgb(248, 248, 248) !important] state_next = write_state;
WE_N = 1'b0;
[backcolor=rgb(248, 248, 248) !important] end
end
[backcolor=rgb(248, 248, 248) !important] write_state: begin
OE_N = 1'b0;
[backcolor=rgb(248, 248, 248) !important] CE_N = 1'b0;
WE_N = 1'b0;
[backcolor=rgb(248, 248, 248) !important] state_next = finish_state;
end
[backcolor=rgb(248, 248, 248) !important] read_state: begin
OE_N = 1'b0;
[backcolor=rgb(248, 248, 248) !important] CE_N = 1'b0;
sram_data_reg_next = sram_data;
[backcolor=rgb(248, 248, 248) !important] state_next = finish_state;
end
[backcolor=rgb(248, 248, 248) !important] finish_state:begin
finish = 1'b1;
[backcolor=rgb(248, 248, 248) !important] state_next = idle_state;
end
[backcolor=rgb(248, 248, 248) !important] default:
state_next = idle_state;
[backcolor=rgb(248, 248, 248) !important] endcase
end
[backcolor=rgb(248, 248, 248) !important]
endmodule
|
|