在“DE2开发板上SRAM的使用”一文中,讨论了怎么操作SRAM,涉及到如何依次将数据存入SRAM的各个地址中,以及如何单次地提取出存入的数据以显示在数码管上。
本文的工作:从SRAM中的任意给定的两个地址中,将其中的数据提取出来,并做加法运算。
////////////////////////////////////////////////////////
/*
操作对象是ALTERA DE2 开发板上的SRAM。
按下KEY[3] 后,变量清零;
按下KEY[1]后,数据在一瞬间填满SRAM中0~262001的地址,LEDG[0]会有指示;
18个SW代表18位的地址。
将SW设置为希望读取的地址后,按下KEY[2],4个数码管会显示16位的数据
按下KEY[0]后,HEX4-HEX7会显示加法结果。选定的地址是3和6,里面存放的数据也是3和6
这里的加法器做的比较粗糙,没有进行溢出、进位等判断。
当然,3+6的结果9在本例中还是能正确显示的。
*/
////////////////////////////////////////////////////////
module SRAM_2(
//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
/////// new code ////////////////////////////////
assign SRAM_OE_N = (!KEY[0] | !KEY[2])?0:1;
//允许按KEY[0]或者是KEY[2]都能实现对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
//////////// new code ///////////////////////////
if(KEY[0] == 0) begin
case (state)
4'b0001: begin
SRAM_DQ <= 'bz;
state<=4'b0010;
end
4'b0010: begin
SRAM_ADDR<=3;
regDATa<=SRAM_DQ;
state<=4'b0100;
end
4'b0100: begin
SRAM_ADDR<=6;
regDATb<=SRAM_DQ;
state<=4'b1000;
end
4'b1000: begin
regDATc<=regDATa+regDATb;
HEX4 <= set_HEX({1'b0,regDATc[3:0]});
HEX5 <= set_HEX({1'b0,regDATc[7:4]});
HEX6 <= set_HEX({1'b0,regDATc[11:8]});
HEX7 <= set_HEX({1'b0,regDATc[15:12]});
state<=4'b0001;
end
default: state<=4'b0001;
endcase
end
/////////////////////////////////////////////////////////////////
end
/////////////////////// newcode /////////////////////////////
reg [15:0] regDATa,regDATb,regDATc;
reg [3:0]state;
//////////////////////////////////////////////////////////////////
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