//DE2开发板上512KB容量的SRAM读写
//按KEY[1]可在iWR_ADDR~iWR_MAX_ADDR-1地址范围内写入数据,数据逐个加一
//按KEY[2]可以读出存放在地址中的数据,地址由18位的拨档开关指定
//系统复位信号DLY_RST由系统时钟CLOCK_50控制
//采用PLL,使写入速度由10MHz时钟控制
//版本v1.1:修正v1.0中多次按KEY[1]后某些地址中的数据会出现FFFF的错误。
module DE2_SRAM(
//HOST Side
//output
HEX0,
HEX1,
HEX2,
HEX3, //display the data saved in the address assigned by SW
LEDG, //indicate which KEY is pressed
LEDR, //indicate which SW is changed
//input
SW, //assign an address
KEY, //KEY[1]--write; KEY[2]--read
CLOCK_50,
//SRAM Side
//inout
SRAM_DQ,
//output
SRAM_ADDR,
SRAM_CE_N,
SRAM_OE_N,
SRAM_WE_N,
SRAM_UB_N,
SRAM_LB_N
);
output [6:0] HEX0, HEX1, HEX2, HEX3;
output [8:0] LEDG;
output [17:0] LEDR;
input [17:0] SW;//use to assign address
input [3:0] KEY;//KEY[2]--Read;KEY[1]--Write
input CLOCK_50;
//SRAM Side
inout [15:0] SRAM_DQ;
output SRAM_CE_N, SRAM_OE_N, SRAM_WE_N, SRAM_UB_N, SRAM_LB_N;
output [17:0]SRAM_ADDR;
wire [15:0]hdata;//data saved in the assigned address
wire clk;
wire DLY_RST;
CLK_10MHZ (.inclk0(CLOCK_50),.c0(clk));
SRAM_controller sram_controller(
//Host Side
.iCLK (clk),
.iRST_N (DLY_RST),//KEY[3]),
.iWR (!KEY[1]),
.iRD (!KEY[2]),
.iWR_ADDR (0),//0),
.iWR_MAX_ADDR (100),//262100),//write from iWR_ADDR to iWR_MAX_ADDR-1
.iRD_ADDR (SW),
.oRD_DATA (hdata),
//SRAM Side
.SRAM_DQ (SRAM_DQ),
.SRAM_ADDR (SRAM_ADDR),
.SRAM_CE_N (SRAM_CE_N),
.SRAM_OE_N (SRAM_OE_N),
.SRAM_WE_N (SRAM_WE_N),
.SRAM_UB_N (SRAM_UB_N),
.SRAM_LB_N (SRAM_LB_N)
);
Reset_Delay r0(.iCLK(clk),.oRESET(DLY_RST));
assign LEDR= SW;//show which SW moved
assign LEDG={4'b0000,!KEY[3],!KEY[2],!KEY[1],!KEY[0]};//show which key pressed
//display the 16-bit data saved in the assigned address(SW)
assign HEX0= set_HEX({1'b0,hdata[3:0]});
assign HEX1= set_HEX({1'b0,hdata[7:4]});
assign HEX2= set_HEX({1'b0,hdata[11:8]});
assign HEX3= set_HEX({1'b0,hdata[15:12]});
//table of HEX
function [6:0] set_HEX;
input [4:0] num;
begin
case(num)
5'b00000: set_HEX = 7'b100_0000; //0
5'b00001: set_HEX = 7'b111_1001; //1
5'b00010: set_HEX = 7'b010_0100; //2
5'b00011: set_HEX = 7'b011_0000; //3
5'b00100: set_HEX = 7'b001_1001; //4
5'b00101: set_HEX = 7'b001_0010; //5
5'b00110: set_HEX = 7'b000_0010; //6
5'b00111: set_HEX = 7'b111_1000; //7
5'b01000: set_HEX = 7'b000_0000; //8
5'b01001: set_HEX = 7'b001_1000; //9
5'b01010: set_HEX = 7'b000_1000; //A
5'b01011: set_HEX = 7'b000_0011; //B
5'b01100: set_HEX = 7'b100_0110; //C
5'b01101: set_HEX = 7'b010_0001; //D
5'b01110: set_HEX = 7'b000_0110; //E
5'b01111: set_HEX = 7'b000_1110; //F
default: set_HEX = 7'b111_1111; //default
endcase
end
endfunction
endmodule
//DE2_SRAM v1.2中所使用的SRAM控制器
//可以给定写入的地址范围:iWR_ADDR~iWR_MAX_ADDR-1
//读取数据的地址:iRD_ADDR
//读出的数据:oRD_DATA
module SRAM_controller(
//Host Side
iCLK,
iRST_N,
iWR,
iRD,
iWR_ADDR,
iWR_MAX_ADDR,
iRD_ADDR,
oRD_DATA,
//SRAM Side
SRAM_DQ,
SRAM_ADDR,
SRAM_CE_N,
SRAM_OE_N,
SRAM_WE_N,
SRAM_UB_N,
SRAM_LB_N
);
//HOST Side
input iCLK,iRST_N,iWR,iRD;
input [17:0]iWR_ADDR,iWR_MAX_ADDR,iRD_ADDR;
output reg [15:0]oRD_DATA;
//SRAM Side
inout [15:0]SRAM_DQ;
output SRAM_CE_N, SRAM_OE_N, SRAM_WE_N, SRAM_UB_N, SRAM_LB_N;
output [17:0] SRAM_ADDR;
reg SRAM_WE_N;
reg [15:0] SRAM_DQ;
reg [17:0] SRAM_ADDR;
assign SRAM_CE_N = 0;//SRAM is always worked
assign SRAM_UB_N = 0;//upper byte is available
assign SRAM_LB_N = 0;//lower byte is available
assign SRAM_OE_N = 0;//output enable (not effect write)
reg [15:0] tmp_data;
reg [17:0] rWR_ADDR,rWR_MAX_ADDR;
always @(posedge iCLK or negedge iRST_N) begin
//system reset
if(!iRST_N) begin
rWR_ADDR <= iWR_ADDR;//0;
rWR_MAX_ADDR <= iWR_MAX_ADDR;//262100;
tmp_data <= 0;
SRAM_WE_N <= 0;
end
else begin
//write process
if ((iWR==1) && (rWR_ADDR<iWR_MAX_ADDR)) begin
SRAM_WE_N <= 0;
rWR_ADDR<=rWR_ADDR+1'b1;
tmp_data <= tmp_data + 1'b1;
SRAM_DQ <= tmp_data;
SRAM_ADDR <= rWR_ADDR;
end
else begin
SRAM_WE_N <= 1;//write disable
tmp_data <= 0;
rWR_ADDR <= 0;
end
//read process
if (iRD==1) begin
SRAM_DQ <= 16'hzzzz;//SRAM_DQ must be set to z before read
SRAM_ADDR <= iRD_ADDR;
oRD_DATA<=SRAM_DQ;
end
end
end
endmodule
////////////////////////////////////////////////////////
/*
操作对象是ALTERA DE2 开发板上的SRAM。
按下KEY[3] 后,变量清零;
按下KEY[1]后,数据在一瞬间填满SRAM中0~262001的地址,LEDG[0]会有指示;
18个SW代表18位的地址。
将SW设置为希望读取的地址后,按下KEY[2],4个数码管会显示16位的数据
版本v1.0:bug--在不按复位的情况下,多次按KEY[1]后,某些地址中的数据会变成FFFF。
*/
////////////////////////////////////////////////////////
module DE2_SRAM(
//output
HEX0,
HEX1,
HEX2,
HEX3,
LEDG,
LEDR, //indicate which SW is changed
//input
SW,
KEY,
CLOCK_50,
//inout
SRAM_DQ,
//output
SRAM_ADDR,
SRAM_CE_N,
SRAM_OE_N,
SRAM_WE_N,
SRAM_UB_N,
SRAM_LB_N
);
output [6:0] HEX0, HEX1, HEX2, HEX3;
reg [6:0] HEX0, HEX1, HEX2, HEX3;
output [8:0] LEDG;
reg [8:0] LEDG;
output [17:0] LEDR;
input [17:0] SW;
input [3:0] KEY;
input CLOCK_50;
//SRAM
inout [15:0] SRAM_DQ;
reg [15:0] SRAM_DQ;
output SRAM_CE_N, SRAM_OE_N, SRAM_WE_N, SRAM_UB_N, SRAM_LB_N;
output [17:0] SRAM_ADDR;
reg [17:0] SRAM_ADDR;
assign SRAM_CE_N = 0;//始终选中SRAM
assign SRAM_OE_N = (KEY[2] == 0)?0:1;
//根据datasheet,只有OE脚为低电平才能输出数据
//KEY按下,对应低电平;松开为高电平
//按住KEY[2],在SW设定地址后,可输出该地址中存储的数据
////////////// my code ////////////////////
//assign SRAM_WE_N=(!KEY[3] | !KEY[1])?0:1;
///////////////////////////////////////////
assign SRAM_UB_N = 0;
assign SRAM_LB_N = 0;
//允许输出数据的高八位(UB)和低八位(LB)
//任意一个置1,则相应的8位输出为FF(高阻)
assign SRAM_WE_N = (KEY[1] == 0)?0:1;
//按datasheet,WE为高电平时,读操作;低电平时为写操作
//KEY[1]按下(==0),对应写操作;松开则为读操作
//松开KEY[1]和KEY[2],WE和OE都为高电平,输出高阻
assign LEDR = SW;
reg [15:0] tmp_data;
reg [17:0] tmp_addr;
wire clk;
//使用PLL锁频,将频率降到10MHz,控制写入的速度,不需要改相位
CLK_10MHZ M1(
.inclk0(CLOCK_50),
.c0(clk)
);
always @(posedge clk) begin
if(KEY[3] == 0) begin
tmp_addr <= 0;
tmp_data <= 0;
///////////mycode///////////////
//SRAM_DQ<=0;
//SRAM_ADDR<=SRAM_ADDR+1'b1;
////////////////////////////////
end
//按住KEY[3],在clk上升沿到来时,将tmp_addr和tmp_data清零
//无法擦除SRAM里面的数据
//改用mycode代码可以擦除SRAM里面所有数据
else if((KEY[1] == 0) && (tmp_addr < 262001)) begin
SRAM_DQ <= tmp_data; //数据端口赋值后,需要在后面设置成高阻
//否则会锁存,即保留最后一次的赋值
SRAM_ADDR <= tmp_addr;
tmp_data <= tmp_data + 1;
tmp_addr <= tmp_addr + 1;
end
else begin//
// SRAM_DQ <= 'bz; //here set data prot to High Z
// SRAM_ADDR <= 'bz;
end
//SRAM写操作结束后,若想读取数据,必须设置成高阻
if(KEY[2] == 0) begin
SRAM_DQ <= 'bz; //OR here set data port to High Z
SRAM_ADDR <= SW;
HEX0 <= set_HEX({1'b0,SRAM_DQ[3:0]});
HEX1 <= set_HEX({1'b0,SRAM_DQ[7:4]});
HEX2 <= set_HEX({1'b0,SRAM_DQ[11:8]});
HEX3 <= set_HEX({1'b0,SRAM_DQ[15:12]});
end
end
always @(posedge clk) begin
if(KEY[3] == 0)
LEDG[0] = 0;
else if(tmp_addr >= 262001)
LEDG[0] = 1;
else
LEDG[0] = 0;
end
//table of HEX
function [6:0] set_HEX;
input [4:0] num;
begin
case(num)
5'b00000: set_HEX = 7'b100_0000; //0
5'b00001: set_HEX = 7'b111_1001; //1
5'b00010: set_HEX = 7'b010_0100; //2
5'b00011: set_HEX = 7'b011_0000; //3
5'b00100: set_HEX = 7'b001_1001; //4
5'b00101: set_HEX = 7'b001_0010; //5
5'b00110: set_HEX = 7'b000_0010; //6
5'b00111: set_HEX = 7'b111_1000; //7
5'b01000: set_HEX = 7'b000_0000; //8
5'b01001: set_HEX = 7'b001_1000; //9
5'b01010: set_HEX = 7'b000_1000; //A
5'b01011: set_HEX = 7'b000_0011; //B
5'b01100: set_HEX = 7'b100_0110; //C
5'b01101: set_HEX = 7'b010_0001; //D
5'b01110: set_HEX = 7'b000_0110; //E
5'b01111: set_HEX = 7'b000_1110; //F
default: set_HEX = 7'b111_1111; //default
endcase
end
endfunction
endmodule