//---------------------------------------------------------------------------- // Wishbone SRAM controller //---------------------------------------------------------------------------- module wb_sram16 #( parameter adr_width = 18, parameter latency = 0 // 0 .. 7 ) ( input clk, input reset, // Wishbone interface input wb_stb_i, input wb_cyc_i, output reg wb_ack_o, input wb_we_i, input [31:0] wb_adr_i, input [3:0] wb_sel_i, input [31:0] wb_dat_i, output reg [31:0] wb_dat_o, // SRAM connection output reg [adr_width-1:0] sram_adr, inout [15:0] sram_dat, output reg [1:0] sram_be_n, // Byte Enable output reg sram_ce_n, // Chip Enable output reg sram_oe_n, // Output Enable output reg sram_we_n // Write Enable ); //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- // Wishbone handling wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i & ~wb_ack_o; wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i & ~wb_ack_o; // Translate wishbone address to sram address wire [adr_width-1:0] adr1 = { wb_adr_i[adr_width:2], 1'b0 }; wire [adr_width-1:0] adr2 = { wb_adr_i[adr_width:2], 1'b1 }; // Tri-State-Driver reg [15:0] wdat; reg wdat_oe; assign sram_dat = wdat_oe ? wdat : 16'bz; // Latency countdown reg [2:0] lcount; //---------------------------------------------------------------------------- // State Machine //---------------------------------------------------------------------------- parameter s_idle = 0; parameter s_read1 = 1; parameter s_read2 = 2; parameter s_write1 = 3; parameter s_write2 = 4; parameter s_write3 = 5; reg [2:0] state; always @(posedge clk) begin if (reset) begin state <= s_idle; lcount <= 0; wb_ack_o <= 0; end else begin case (state) s_idle: begin wb_ack_o <= 0; if (wb_rd) begin sram_ce_n <= 0; sram_oe_n <= 0; sram_we_n <= 1; sram_adr <= adr1; sram_be_n <= 2'b00; wdat_oe <= 0; lcount <= latency; state <= s_read1; end else if (wb_wr) begin sram_ce_n <= 0; sram_oe_n <= 1; sram_we_n <= 0; sram_adr <= adr1; sram_be_n <= ~wb_sel_i[1:0]; wdat <= wb_dat_i[15:0]; wdat_oe <= 1; lcount <= latency; state <= s_write1; end else begin sram_ce_n <= 1; sram_oe_n <= 1; sram_we_n <= 1; end end s_read1: begin if (lcount != 0) begin lcount <= lcount - 1; end else begin wb_dat_o[15:0] <= sram_dat; sram_ce_n <= 0; sram_oe_n <= 0; sram_we_n <= 1; sram_adr <= adr2; sram_be_n <= 2'b00; wdat_oe <= 0; lcount <= latency; state <= s_read2; end end s_read2: begin if (lcount != 0) begin lcount <= lcount - 1; end else begin wb_dat_o[31:16] <= sram_dat; wb_ack_o <= 1; sram_ce_n <= 1; sram_oe_n <= 1; sram_we_n <= 1; state <= s_idle; end end s_write1: begin if (lcount != 0) begin lcount <= lcount - 1; end else begin sram_ce_n <= 0; sram_oe_n <= 1; sram_we_n <= 1; state <= s_write2; end end s_write2: begin sram_ce_n <= 0; sram_oe_n <= 1; sram_we_n <= 0; sram_adr <= adr2; sram_be_n <= ~wb_sel_i[3:2]; wdat <= wb_dat_i[31:16]; wdat_oe <= 1; lcount <= latency; wb_ack_o <= 1; state <= s_write3; end s_write3: begin wb_ack_o <= 0; if (lcount != 0) begin lcount <= lcount - 1; end else begin sram_ce_n <= 1; sram_oe_n <= 1; sram_we_n <= 1; wdat_oe <= 0; state <= s_idle; end end endcase end end endmodule