root / usrp2 / fifo / buffer_int2.v @ 4eba6ddc
History | View | Annotate | Download (4.55 KB)
| 1 | 8d6e6985 | Matt Ettus | |
|---|---|---|---|
| 2 | // FIFO Interface to the 2K buffer RAMs |
||
| 3 | // Read port is read-acknowledge |
||
| 4 | // FIXME do we want to be able to interleave reads and writes? |
||
| 5 | |||
| 6 | module buffer_int2 |
||
| 7 | #(parameter BASE = 0, |
||
| 8 | parameter BUF_SIZE = 9) |
||
| 9 | 1154d5be | Matt Ettus | (input clk, input rst, |
| 10 | 8d6e6985 | Matt Ettus | input set_stb, input [7:0] set_addr, input [31:0] set_data, |
| 11 | output [31:0] status, |
||
| 12 | |||
| 13 | // Wishbone interface to RAM |
||
| 14 | input wb_clk_i, |
||
| 15 | input wb_rst_i, |
||
| 16 | input wb_we_i, |
||
| 17 | input wb_stb_i, |
||
| 18 | input [15:0] wb_adr_i, |
||
| 19 | input [31:0] wb_dat_i, |
||
| 20 | output [31:0] wb_dat_o, |
||
| 21 | output reg wb_ack_o, |
||
| 22 | |||
| 23 | // Write FIFO Interface |
||
| 24 | input [35:0] wr_data_i, |
||
| 25 | input wr_ready_i, |
||
| 26 | output wr_ready_o, |
||
| 27 | |||
| 28 | // Read FIFO Interface |
||
| 29 | output [35:0] rd_data_o, |
||
| 30 | output rd_ready_o, |
||
| 31 | input rd_ready_i |
||
| 32 | ); |
||
| 33 | |||
| 34 | aed2e0d4 | Matt Ettus | reg [15:0] rd_addr, wr_addr; // Handle pkt bigger than buffer |
| 35 | wire [15:0] rd_addr_next = rd_addr + 1; |
||
| 36 | reg [15:0] rd_length; |
||
| 37 | |||
| 38 | 8d6e6985 | Matt Ettus | wire [31:0] ctrl; |
| 39 | 87d57ac2 | Matt Ettus | wire wr_done, wr_error, wr_idle; |
| 40 | wire rd_done, rd_error, rd_idle; |
||
| 41 | wire we, en, go; |
||
| 42 | |||
| 43 | wire read = ctrl[3]; |
||
| 44 | wire rd_clear = ctrl[2]; |
||
| 45 | wire write = ctrl[1]; |
||
| 46 | wire wr_clear = ctrl[0]; |
||
| 47 | 8d6e6985 | Matt Ettus | |
| 48 | 87d57ac2 | Matt Ettus | reg [2:0] rd_state, wr_state; |
| 49 | reg rd_sop, rd_eop; |
||
| 50 | wire wr_sop, wr_eop; |
||
| 51 | reg [1:0] rd_occ; |
||
| 52 | wire [1:0] wr_occ; |
||
| 53 | 8d6e6985 | Matt Ettus | |
| 54 | localparam IDLE = 3'd0; |
||
| 55 | localparam PRE_READ = 3'd1; |
||
| 56 | localparam READING = 3'd2; |
||
| 57 | localparam WRITING = 3'd3; |
||
| 58 | localparam ERROR = 3'd4; |
||
| 59 | localparam DONE = 3'd5; |
||
| 60 | 87d57ac2 | Matt Ettus | |
| 61 | // read state machine |
||
| 62 | 8d6e6985 | Matt Ettus | always @(posedge clk) |
| 63 | 87d57ac2 | Matt Ettus | if(rst | (rd_clear & go)) |
| 64 | 8d6e6985 | Matt Ettus | begin |
| 65 | 87d57ac2 | Matt Ettus | rd_state <= IDLE; |
| 66 | 8d6e6985 | Matt Ettus | rd_sop <= 0; |
| 67 | rd_eop <= 0; |
||
| 68 | rd_occ <= 0; |
||
| 69 | end |
||
| 70 | else |
||
| 71 | 87d57ac2 | Matt Ettus | case(rd_state) |
| 72 | IDLE : |
||
| 73 | if(go & read) |
||
| 74 | 8d6e6985 | Matt Ettus | begin |
| 75 | 87d57ac2 | Matt Ettus | rd_addr <= 0; |
| 76 | rd_state <= PRE_READ; |
||
| 77 | aed2e0d4 | Matt Ettus | rd_length <= ctrl[31:16]; |
| 78 | 8d6e6985 | Matt Ettus | end |
| 79 | 87d57ac2 | Matt Ettus | |
| 80 | PRE_READ : |
||
| 81 | begin |
||
| 82 | rd_state <= READING; |
||
| 83 | 17450097 | Josh Blum | rd_addr <= rd_addr_next; |
| 84 | 87d57ac2 | Matt Ettus | rd_occ <= 2'b00; |
| 85 | rd_sop <= 1; |
||
| 86 | rd_eop <= 0; |
||
| 87 | end |
||
| 88 | |||
| 89 | READING : |
||
| 90 | if(rd_ready_i) |
||
| 91 | 8d6e6985 | Matt Ettus | begin |
| 92 | 87d57ac2 | Matt Ettus | rd_sop <= 0; |
| 93 | 17450097 | Josh Blum | rd_addr <= rd_addr_next; |
| 94 | if(rd_addr_next == rd_length) |
||
| 95 | 8d6e6985 | Matt Ettus | begin |
| 96 | 87d57ac2 | Matt Ettus | rd_eop <= 1; |
| 97 | // FIXME assign occ here |
||
| 98 | rd_occ <= 0; |
||
| 99 | end |
||
| 100 | else |
||
| 101 | rd_eop <= 0; |
||
| 102 | if(rd_eop) |
||
| 103 | rd_state <= DONE; |
||
| 104 | end |
||
| 105 | |||
| 106 | endcase // case(rd_state) |
||
| 107 | |||
| 108 | // write state machine |
||
| 109 | always @(posedge clk) |
||
| 110 | 35ae7bc8 | Josh Blum | if(rst | (wr_clear & go)) |
| 111 | 87d57ac2 | Matt Ettus | wr_state <= IDLE; |
| 112 | else |
||
| 113 | case(wr_state) |
||
| 114 | IDLE : |
||
| 115 | if(go & write) |
||
| 116 | begin |
||
| 117 | wr_addr <= 0; |
||
| 118 | wr_state <= WRITING; |
||
| 119 | end |
||
| 120 | |||
| 121 | WRITING : |
||
| 122 | if(wr_ready_i) |
||
| 123 | begin |
||
| 124 | wr_addr <= wr_addr + 1; |
||
| 125 | if(wr_sop & wr_eop) |
||
| 126 | wr_state <= ERROR; // Should save OCC flags here |
||
| 127 | else if(wr_eop) |
||
| 128 | wr_state <= DONE; |
||
| 129 | end // if (wr_ready_i) |
||
| 130 | endcase // case(wr_state) |
||
| 131 | 8d6e6985 | Matt Ettus | |
| 132 | assign rd_data_o[35:32] = { rd_occ[1:0], rd_eop, rd_sop };
|
||
| 133 | 87d57ac2 | Matt Ettus | assign rd_ready_o = (rd_state == READING); |
| 134 | 8d6e6985 | Matt Ettus | |
| 135 | assign wr_sop = wr_data_i[32]; |
||
| 136 | assign wr_eop = wr_data_i[33]; |
||
| 137 | assign wr_occ = wr_data_i[35:34]; |
||
| 138 | 87d57ac2 | Matt Ettus | assign wr_ready_o = (wr_state == WRITING); |
| 139 | 8d6e6985 | Matt Ettus | |
| 140 | 87d57ac2 | Matt Ettus | assign we = (wr_state == WRITING); // always write to avoid timing issue |
| 141 | assign en = ~((rd_state==READING)& ~rd_ready_i); // FIXME potential critical path |
||
| 142 | 8d6e6985 | Matt Ettus | |
| 143 | 87d57ac2 | Matt Ettus | assign rd_done = (rd_state == DONE); |
| 144 | assign wr_done = (wr_state == DONE); |
||
| 145 | assign rd_error = (rd_state == ERROR); |
||
| 146 | assign wr_error = (wr_state == ERROR); |
||
| 147 | assign rd_idle = (rd_state == IDLE); |
||
| 148 | assign wr_idle = (wr_state == IDLE); |
||
| 149 | 8d6e6985 | Matt Ettus | |
| 150 | aed2e0d4 | Matt Ettus | wire [BUF_SIZE-1:0] wr_addr_clip = (|wr_addr[15:BUF_SIZE]) ? {BUF_SIZE{1'b1}} : wr_addr[BUF_SIZE-1:0];
|
| 151 | |||
| 152 | 87d57ac2 | Matt Ettus | ram_2port #(.DWIDTH(32),.AWIDTH(BUF_SIZE)) buffer_in // CPU reads here |
| 153 | (.clka(wb_clk_i),.ena(wb_stb_i),.wea(1'b0), |
||
| 154 | .addra(wb_adr_i[BUF_SIZE+1:2]),.dia(0),.doa(wb_dat_o), |
||
| 155 | .clkb(clk),.enb(1'b1),.web(we), |
||
| 156 | aed2e0d4 | Matt Ettus | .addrb(wr_addr_clip),.dib(wr_data_i[31:0]),.dob()); |
| 157 | 87d57ac2 | Matt Ettus | |
| 158 | ram_2port #(.DWIDTH(32),.AWIDTH(BUF_SIZE)) buffer_out // CPU writes here |
||
| 159 | 8d6e6985 | Matt Ettus | (.clka(wb_clk_i),.ena(wb_stb_i),.wea(wb_we_i), |
| 160 | 87d57ac2 | Matt Ettus | .addra(wb_adr_i[BUF_SIZE+1:2]),.dia(wb_dat_i),.doa(), |
| 161 | .clkb(clk),.enb(en),.web(1'b0), |
||
| 162 | aed2e0d4 | Matt Ettus | .addrb(rd_addr[BUF_SIZE-1:0]),.dib(0),.dob(rd_data_o[31:0])); |
| 163 | 8d6e6985 | Matt Ettus | |
| 164 | always @(posedge wb_clk_i) |
||
| 165 | if(wb_rst_i) |
||
| 166 | wb_ack_o <= 0; |
||
| 167 | else |
||
| 168 | wb_ack_o <= wb_stb_i & ~wb_ack_o; |
||
| 169 | |||
| 170 | setting_reg #(.my_addr(BASE)) |
||
| 171 | sreg(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),.in(set_data), |
||
| 172 | .out(ctrl),.changed(go)); |
||
| 173 | |||
| 174 | aed2e0d4 | Matt Ettus | assign status = { wr_addr,
|
| 175 | 87d57ac2 | Matt Ettus | 8'b0,1'b0,rd_idle,rd_error,rd_done, 1'b0,wr_idle,wr_error,wr_done}; |
| 176 | 8d6e6985 | Matt Ettus | |
| 177 | endmodule // buffer_int2 |