Skip to content

Instantly share code, notes, and snippets.

@wnew
Created November 13, 2012 07:34
Show Gist options
  • Save wnew/4064496 to your computer and use it in GitHub Desktop.
Save wnew/4064496 to your computer and use it in GitHub Desktop.
Parametrised BRAM wishbone bus interface
//============================================================================//
// //
// Parameterize BRAM with wishbone interface //
// //
// Module name: bram_wb //
// Desc: parameterized dual-port bram with a wishbone interface on one //
// port. //
// Date: June 2012 //
// Developer: Wesley New //
// Licence: GNU General Public License ver 3 //
// Notes: //
// //
//============================================================================//
module bram_wb #(
//=============
// Parameters
//=============
parameter DEV_BASE_ADDR = 0,
parameter DEV_HIGH_ADDR = 32,
parameter BUS_DATA_WIDTH = 32,
parameter BUS_ADDR_WIDTH = 8,
parameter BUS_BE_WIDTH = 4,
parameter RAM_ADDR_WIDTH = 8,
parameter SLEEP_COUNT = 4
) (
//===============
// Fabric Ports
//===============
input fabric_clk,
input fabric_rst,
input fabric_we,
input [RAM_ADDR_WIDTH-1:0] fabric_addr,
input [RAM_DATA_WIDTH-1:0] fabric_data_in,
output [RAM_DATA_WIDTH-1:0] fabric_data_out,
//=================
// Wishbone Ports
//=================
input wire wbs_clk_i,
input wire wbs_rst_i,
input wire wbs_cyc_i,
input wire wbs_stb_i,
input wire wbs_we_i,
input wire [BUS_BE_WIDTH-1:0] wbs_sel_i,
input wire [BUS_ADDR_WIDTH-1:0] wbs_adr_i,
input wire [BUS_DATA_WIDTH-1:0] wbs_dat_i,
output reg [BUS_DATA_WIDTH-1:0] wbs_dat_o,
output reg wbs_ack_o
);
//===================
// Local Parameters
//===================
localparam RAM_DATA_WIDTH = BUS_ADDR_WIDTH;
localparam DATA_DEPTH = 2 ** RAM_ADDR_WIDTH;
//======================
// Local Reg and Wires
//======================
wire [RAM_DATA_WIDTH-1:0] read_data;
reg [RAM_DATA_WIDTH-1:0] write_data;
reg [RAM_ADDR_WIDTH-1:0] ram_adr;
reg [3:0] ram_sleep;
reg en_ram;
//================
// BRAM instance
//================
bram_sync_dp #(
.RAM_DATA_WIDTH (RAM_DATA_WIDTH),
.RAM_ADDR_WIDTH (RAM_ADDR_WIDTH)
) bram_inst (
.rst (wbs_rst_i || fabric_rst),
.en (en_ram),
.a_clk (fabric_clk),
.a_wr (fabric_we),
.a_addr (fabric_addr),
.a_data_in (fabric_data_in),
.a_data_out (fabric_data_out),
.b_clk (wbs_clk_i),
.b_wr (wbs_we_i),
.b_addr (ram_adr),
.b_data_in (write_data),
.b_data_out (read_data)
);
wire adr_match = wbs_adr_i >= DEV_BASE_ADDR && wbs_adr_i <= DEV_HIGH_ADDR;
// TODO: make sure the logic below is working!!!!
//=================
// Wishbone Logic
//=================
always @ (posedge wbs_clk_i) begin
if (fabric_rst || wbs_rst_i) begin
wbs_dat_o <= 32'h00000000;
wbs_ack_o <= 0;
ram_sleep <= SLEEP_COUNT;
ram_adr <= 0;
en_ram <= 0;
end
else begin
//when the master acks our ack, then put our ack down
if (wbs_ack_o & ~wbs_stb_i) begin
wbs_ack_o <= 0;
en_ram <= 0;
end
if (adr_match & wbs_stb_i & wbs_cyc_i) begin
//master is requesting somethign
en_ram <= 1;
ram_adr <= wbs_adr_i[BUS_ADDR_WIDTH-1:0];
if (wbs_we_i) begin
//write request
//the bram module will handle all the writes
write_data <= wbs_dat_i;
//$display ("write a:%h, d:%h", wbs_adr_i[ADDR_WIDTH:0], wbs_dat_i);
end
else begin
//read request
wbs_dat_o <= read_data;
//wbs_dat_o <= wbs_adr_i;
//$display ("read a:%h, d:%h", wbs_adr_i[ADDR_WIDTH:0], read_data);
end
if (ram_sleep > 0) begin
ram_sleep <= ram_sleep - 1;
end
else begin
wbs_ack_o <= 1;
ram_sleep <= SLEEP_COUNT;
end
end
end
end
endmodule
//============================================================================//
// //
// BRAM wishbone test bench //
// //
// Module name: bram_wb_tb //
// Desc: runs and tests the bram_wb module, and provides and interface //
// to test the module from Python (MyHDL) //
// This uses a dual port bram with one ports connected to the //
// wishbone bus and the other to the fabric //
// Date: June 2012 //
// Developer: Wesley New //
// Licence: GNU General Public License ver 3 //
// Notes: This only tests the basic functionality of the module, more //
// comprehensive testing is done in the python test file //
// //
//============================================================================//
module bram_wb_tb;
//=====================
// local wires & regs
//=====================
reg wbs_clk_i;
reg wbs_rst_i;
reg wbs_cyc_i;
reg wbs_stb_i;
reg wbs_we_i;
reg [3:0] wbs_sel_i;
reg [7:0] wbs_adr_i;
reg [31:0] wbs_dat_i;
wire [31:0] wbs_dat_o;
wire wbs_ack_o;
reg fabric_clk;
reg fabric_rst;
reg fabric_we;
reg [7:0] fabric_addr;
reg [31:0] fabric_data_in;
wire [31:0] fabric_data_out;
//=====================================
// instance, "(d)esign (u)nder (t)est"
//=====================================
bram_wb #(
.DATA_WIDTH (32),
.ADDR_WIDTH (8),
.SLEEP_COUNT (4)
//.C_BASEADDR (32'h00000000),
//.C_HIGHADDR (32'h0000FFFF)
) dut (
.fabric_clk (fabric_clk),
.fabric_rst (fabric_rst),
.fabric_we (fabric_we),
.fabric_addr (fabric_addr),
.fabric_data_in (fabric_data_in),
.fabric_data_out (fabric_data_out),
.wbs_clk_i (wbs_clk_i),
.wbs_rst_i (wbs_rst_i),
.wbs_cyc_i (wbs_cyc_i),
.wbs_stb_i (wbs_stb_i),
.wbs_we_i (wbs_we_i),
.wbs_adr_i (wbs_adr_i),
.wbs_dat_i (wbs_dat_i),
.wbs_dat_o (wbs_dat_o),
.wbs_ack_o (wbs_ack_o)
);
//==============
// Initialize
//==============
initial
begin
$dumpvars;
wbs_clk_i = 0;
wbs_sel_i = 4'hE;
wbs_stb_i = 1;
wbs_cyc_i = 1;
wbs_we_i = 1;
wbs_adr_i = 8'h00;
wbs_dat_i = 32'hEEEEEEEE;
#5
wbs_stb_i = 0;
wbs_cyc_i = 0;
#5
wbs_adr_i = 8'h01;
wbs_stb_i = 1;
wbs_cyc_i = 1;
wbs_we_i = 0;
#20 $finish;
end
//=====================
// Simulate the Clock
//=====================
always #1
wbs_clk_i = ~wbs_clk_i;
`endif
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment