mirror of
https://github.com/RangeNetworks/openbts.git
synced 2025-10-23 07:42:01 +00:00
git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@3457 19bc5d8c-e614-43d4-8b26-e1612bc8e597
108 lines
3.2 KiB
Verilog
108 lines
3.2 KiB
Verilog
module channel_ram
|
|
( // System
|
|
input txclk, input reset,
|
|
// USB side
|
|
input [31:0] datain, input WR, input WR_done, output have_space,
|
|
// Reader side
|
|
output [31:0] dataout, input RD, input RD_done, output packet_waiting);
|
|
|
|
reg [6:0] wr_addr, rd_addr;
|
|
reg [1:0] which_ram_wr, which_ram_rd;
|
|
reg [2:0] nb_packets;
|
|
|
|
reg [31:0] ram0 [0:127];
|
|
reg [31:0] ram1 [0:127];
|
|
reg [31:0] ram2 [0:127];
|
|
reg [31:0] ram3 [0:127];
|
|
|
|
reg [31:0] dataout0;
|
|
reg [31:0] dataout1;
|
|
reg [31:0] dataout2;
|
|
reg [31:0] dataout3;
|
|
|
|
wire wr_done_int;
|
|
wire rd_done_int;
|
|
wire [6:0] rd_addr_final;
|
|
wire [1:0] which_ram_rd_final;
|
|
|
|
// USB side
|
|
always @(posedge txclk)
|
|
if(WR & (which_ram_wr == 2'd0)) ram0[wr_addr] <= datain;
|
|
|
|
always @(posedge txclk)
|
|
if(WR & (which_ram_wr == 2'd1)) ram1[wr_addr] <= datain;
|
|
|
|
always @(posedge txclk)
|
|
if(WR & (which_ram_wr == 2'd2)) ram2[wr_addr] <= datain;
|
|
|
|
always @(posedge txclk)
|
|
if(WR & (which_ram_wr == 2'd3)) ram3[wr_addr] <= datain;
|
|
|
|
assign wr_done_int = ((WR && (wr_addr == 7'd127)) || WR_done);
|
|
|
|
always @(posedge txclk)
|
|
if(reset)
|
|
wr_addr <= 0;
|
|
else if (WR_done)
|
|
wr_addr <= 0;
|
|
else if (WR)
|
|
wr_addr <= wr_addr + 7'd1;
|
|
|
|
always @(posedge txclk)
|
|
if(reset)
|
|
which_ram_wr <= 0;
|
|
else if (wr_done_int)
|
|
which_ram_wr <= which_ram_wr + 2'd1;
|
|
|
|
assign have_space = (nb_packets < 3'd3);
|
|
|
|
// Reader side
|
|
// short hand fifo
|
|
// rd_addr_final is what rd_addr is going to be next clock cycle
|
|
// which_ram_rd_final is what which_ram_rd is going to be next clock cycle
|
|
always @(posedge txclk) dataout0 <= ram0[rd_addr_final];
|
|
always @(posedge txclk) dataout1 <= ram1[rd_addr_final];
|
|
always @(posedge txclk) dataout2 <= ram2[rd_addr_final];
|
|
always @(posedge txclk) dataout3 <= ram3[rd_addr_final];
|
|
|
|
assign dataout = (which_ram_rd_final[1]) ?
|
|
(which_ram_rd_final[0] ? dataout3 : dataout2) :
|
|
(which_ram_rd_final[0] ? dataout1 : dataout0);
|
|
|
|
//RD_done is the only way to signal the end of one packet
|
|
assign rd_done_int = RD_done;
|
|
|
|
always @(posedge txclk)
|
|
if (reset)
|
|
rd_addr <= 0;
|
|
else if (RD_done)
|
|
rd_addr <= 0;
|
|
else if (RD)
|
|
rd_addr <= rd_addr + 7'd1;
|
|
|
|
assign rd_addr_final = (reset|RD_done) ? (6'd0) :
|
|
((RD)?(rd_addr+7'd1):rd_addr);
|
|
|
|
always @(posedge txclk)
|
|
if (reset)
|
|
which_ram_rd <= 0;
|
|
else if (rd_done_int)
|
|
which_ram_rd <= which_ram_rd + 2'd1;
|
|
|
|
assign which_ram_rd_final = (reset) ? (2'd0):
|
|
((rd_done_int) ? (which_ram_rd + 2'd1) : which_ram_rd);
|
|
|
|
//packet_waiting is set to zero if rd_done_int is high
|
|
//because there is no guarantee that nb_packets will be pos.
|
|
|
|
assign packet_waiting = (nb_packets > 1) | ((nb_packets == 1)&(~rd_done_int));
|
|
always @(posedge txclk)
|
|
if (reset)
|
|
nb_packets <= 0;
|
|
else if (wr_done_int & ~rd_done_int)
|
|
nb_packets <= nb_packets + 3'd1;
|
|
else if (rd_done_int & ~wr_done_int)
|
|
nb_packets <= nb_packets - 3'd1;
|
|
|
|
endmodule
|