1
0
mirror of git://projects.qi-hardware.com/nn-usb-fpga.git synced 2025-01-10 09:50:14 +02:00
nn-usb-fpga/lm32/logic/sakc/rtl/wb_sram/wb_sram16.v
2010-05-25 21:49:58 -05:00

164 lines
4.0 KiB
Verilog

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