henry

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

//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

posted on 2010-06-05 19:05  yuhengzhou  阅读(1962)  评论(15编辑  收藏  举报