henry

博客园 首页 新随笔 联系 订阅 管理

在“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

 

posted on 2010-06-05 22:23  yuhengzhou  阅读(1442)  评论(0编辑  收藏  举报