Loading dma_adapter.v +121 −94 Original line number Diff line number Diff line Loading @@ -29,26 +29,13 @@ * a big dma data storage and axi interface. So it shall recieve data and control * for 1 burst and pass it to axi. */ /* * For debug only: * DMA write: * 0x0c: |mem[:] => use dbg registers as a source of dma data * 0x10: addr of the buffer * 0x14: size * 0x18: burst len * 0x1c: start dma * 0x20-0x3c - data */ module send_dma #( parameter REGISTERS_CNT = 20 ) ( input wire clk, input wire rst, // dbg iface input wire [32*REGISTERS_CNT - 1:0] mem, input wire dbg_mode, output wire clrstart, // cmd iface input wire cmd_type, // 1 = wr, 0 = rd input wire cmd_val, // issue a cmd Loading @@ -57,9 +44,11 @@ module send_dma #( // data iface input wire [63:0] wr_data_in, output wire wr_val_out, input wire wr_val_in, output wire wr_ack_out, output wire [63:0] rd_data_out, input wire rd_val_in, output wire rd_val_out, input wire rd_ack_in, // membridge iface output wire [7:0] cmd_ad, Loading Loading @@ -89,91 +78,133 @@ module send_dma #( // if not busy and got cmd with val => cmd recieved, assert busy, start a respective algorithm wire wr_start; wire rd_start; wire dma_start; reg wr_done; reg rd_done; reg cmd_type_r; reg cmd_addr_r; reg cmd_val_r; reg [31:7] cmd_addr_r; reg cmd_busy_r; wire set_busy; wire clr_busy; assign set_busy = ~cmd_busy_r & cmd_val; assign clr_busy = cmd_busy_r & (wr_done | rd_done) assign clr_busy = cmd_busy_r & (wr_done | rd_done); assign cmd_busy = cmd_busy_r; assign wr_start = set_busy & cmd_type; assign rd_start = set_busy & ~cmd_type; always @ (posedge clk) begin cmd_type_r <= rst ? 1'b0 : cmd_addr_r <= rst ? 1'b0 : cmd_val_r <= rst ? 1'b0 : cmd_busy_r <= rst ? 1'b0 : ~cmd_busy_r & cmd_val_r cmd_type_r <= rst ? 1'b0 : set_busy ? cmd_type : cmd_type_r; cmd_addr_r <= rst ? 1'b0 : set_busy ? cmd_addr : cmd_addr_r; cmd_busy_r <= (cmd_busy_r | set_busy) & ~rst & ~clr_busy; end /* * Read/write state machine * Read/write data state machine * For better readability the state machine is splitted to two pieces: * the first one is responsible only for the CMD WRITE case handling, * the second one, respectively, for CMD READ * * Each fsm starts a membridge fsm, which, if being 1st time launched, sets up * membridge's registers, or, if have been launched before, just programs read/write * Simultaniously with each fsm starts a membridge fsm, which, if being 1st time launched, * sets up membridge's registers, or, if have been launched before, just programs read/write * address. * * Current implementation is extremely slow, but simple and reliable * After all other parts are implemented and this place occurs to be a bottleneck * then replace it (and may be membridge too) with something more ... pipelined */ reg [1:0] rdwr_state; // check if memberidge was already set up reg membr_is_set; always @ (posedge clk) membr_is_set <= (membr_is_set | dma_start) & ~rst; // common state register reg [3:0] rdwr_state; // Get data from buffer localparam READ_IDLE = 0; localparam READ_ON = 2; localparam READ_DATA = 3; localparam READ_WAIT_ADDR = 3; localparam READ_DATA = 4; reg rd_reset_page; reg rd_next_page; reg rd_data reg rd_data; reg [6:0] rd_data_count; wire rd_stop; wire rd_cnt_to_pull; assign rd_cnt_to_pull == 7'hf; assign rd_stop = rd_ack_in & rd_data_count == rd_cnt_to_pull; assign rd_data_out = rd_data; always @ (posedge clk) if (rst) begin rd_state <= READ_IDLE; rd_done <= rdwr_state <= READ_IDLE; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_en <= 1'b0; end else case (rst) READ_IDLE: begin rdwr_state <= rd_start ? READ_WAIT_ADDR : READ_IDLE; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_en <= 1'b0; end READ_ON: READ_WAIT_ADDR: // wait until address information is sent to the bus and input buffer got data begin rdwr_state <= membr_state == IDLE & rdata_done ? READ_DATA : READ_WAIT_ADDR; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_en <= 1'b0; end READ_DATA: begin rdwr_state <= rd_stop ? READ_IDLE : READ_DATA; rd_done <= rd_stop ? 1'b1 : 1'b0; rd_data_count <= rd_ack_in ? rd_data_count + 1'b1 : rd_data_count; rd_next_page <= rd_stop ? 1'b1 : 1'b0; rd_en <= rd_ack_in ? 1'b1 : 1'b0; end default: // write is processing begin rdwr_state <= READ_IDLE; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_en <= 1'b0; end // Put data into buffer localparam WRITE_IDLE = 0; localparam WRITE_ON = 1; localparam WRITE_DATA = 1; localparam WRITE_WAIT_ADDR = 2; reg wr_en; reg wr_reset_page; reg wr_next_page; reg [63:0] wr_data; reg [6:0] wr_page_offset; reg [6:0] wr_data_count; reg wr_page_ready; reg wr_val; wire [31:0] dw0 = mem[32*9-1:32*8]; wire [31:0] dw1 = mem[32*10-1:32*9]; wire [31:0] dw2 = mem[32*11-1:32*10]; wire [31:0] dw3 = mem[32*12-1:32*11]; wire [6:0] wr_cnt_to_push; wire wr_stop; assign wr_cnt_to_push = 7'hf; assign wr_stop = wr_page_offset == wr_cnt_to_push; assign wr_stop = wr_val_in & wr_data_count == wr_cnt_to_push; assign wr_val_in = wr_val; assign wr_ack_out = wr_val_in & rdwr_state == WRITE_DATA; assign wr_data_in = wr_data; Loading @@ -182,7 +213,7 @@ always @ (posedge clk) if (rst) begin wr_done <= 1'b0; wr_page_offset <= 7'd0; wr_data_count <= 7'd0; wr_val <= 1'b0; wr_data <= 64'h0; wr_next_page <= 1'b0; Loading @@ -195,37 +226,42 @@ always @ (posedge clk) case (wr_state) WRITE_IDLE: begin wr_page_offset <= 7'd0; wr_data_count <= 7'd0; wr_done <= 1'b0; wr_val <= 1'b0; wr_data <= 64'h0; wr_next_page <= 1'b0; wr_reset_page <= wr_start ? 1'b1 : 1'b0; wr_en <= 1'b0; wr_page_ready <= 1'b0; rdwr_state <= wr_start ? WRITE_ON : WRITE_IDLE; rdwr_state <= wr_start ? WRITE_DATA : WRITE_IDLE; end WRITE_ON: WRITE_DATA: begin wr_done <= wr_stop ? 1'b1 : 1'b0; wr_page_offset <= wr_page_offset + 1'b1; wr_val <= 1'b1; wr_data <= ~dbg_mode ? in_data : wr_page_offset[1:0] == 2'b00 ? {dw0, 25'h0, wr_page_offset} : wr_page_offset[1:0] == 2'b01 ? {dw1, 25'h0, wr_page_offset} : wr_page_offset[1:0] == 2'b10 ? {dw2, 25'h0, wr_page_offset} : {dw3, 25'h0, wr_page_offset}; wr_done <= wr_stop & membr_state == IDLE ? 1'b1 : 1'b0; wr_data_count <= wr_val_in ? wr_data_count + 1'b1 : wr_data_count; wr_data <= in_data : wr_next_page <= wr_stop ? 1'b1 : 1'b0; wr_reset_page <= 1'b0; wr_en <= 1'b1; wr_en <= wr_val_in; wr_page_ready <= wr_stop ? 1'b1 : 1'b0; rdwr_state <= wr_stop ? WRITE_IDLE : WRITE_ON; rdwr_state <= wr_stop & membr_state == IDLE ? WRITE_IDLE : wr_stop ? WRITE_WAIT_ADDR : WRITE_DATA; end WRITE_WAIT_ADDR: // in case all data is written into a buffer, but address is still being issued on axi bus begin wr_done <= membr_state == IDLE ? 1'b1 : 1'b0; wr_data_count <= 7'd0; wr_data <= 64'h0; wr_next_page <= 1'b0; wr_reset_page <= 1'b0; wr_en <= 1'b0; wr_page_ready <= 1'b0; rdwr_state <= membr_state == IDLE ? WRITE_IDLE : WRITE_WAIT_ADDR; end default: // read is executed begin wr_done <= 1'b0; wr_page_offset <= 7'd0; wr_val <= 1'b0; wr_data_count <= 7'd0; wr_data <= 64'h0; wr_next_page <= 1'b0; wr_reset_page <= 1'b0; Loading @@ -235,13 +271,12 @@ always @ (posedge clk) end endcase // temporary assigments // membridge interface assigments assign status_start = 1'b0; // no need until status is used assign cmd_wrmem = 1'b0; // for now only writing assign xfer_reset_page_wr = 1'b0; // for now only writing assign buf_rpage_nxt = 1'b0; // for now only writing assign buf_rd = 1'b0; // for now only writing assign xfer_reset_page_wr = 1'b0; assign cmd_wrmem = ~cmd_type_r; assign xfer_reset_page_wr = rd_reset_page; assign buf_rpage_nxt = rd_next_page; assign buf_rd = rd_en; assign buf_wdata = wr_data; assign buf_wr = wr_en; assign buf_wpage_nxt = wr_next_page; Loading @@ -249,16 +284,9 @@ assign xfer_reset_page_rd = wr_reset_page; assign page_ready_chn = cmd_wrmem ? 1'b0 : wr_page_ready; assign frame_done_chn = 1'b1; // compute membridge parameters to corresponding mem register // dma fsm // mode = 0 // width = 4 // size = 0x14 // start = 0 // lo_address = 0x10 // ctrl = 0x1c // len = 0x18 /* * Transfer address and membridge set-ups state machine */ localparam MEMBR_IDLE = 0; localparam MEMBR_MODE = 1; localparam MEMBR_WIDTH = 2; Loading @@ -275,11 +303,8 @@ reg membr_done; reg [2:0] membr_state; reg membr_setup; // indicates the first tick of the state wire membr_inprocess; wire dma_start; assign dma_start = |mem[32*8-1:32*7]; assign clrstart = dma_start & membr_state == MEMBR_IDLE; //assign wr_start = membr_state == MEMBR_CTRL; assign dma_start = wr_start | rd_start; always @ (posedge clk) if (rst) Loading @@ -288,6 +313,7 @@ always @ (posedge clk) membr_addr <= 16'h0; membr_start <= 1'b0; membr_setup <= 1'b0; membr_done <= 1'b0; membr_state <= MEMBR_IDLE; end else Loading @@ -298,7 +324,9 @@ always @ (posedge clk) membr_addr <= 16'h200; membr_start <= dma_start ? 1'b1 : 1'b0; membr_setup <= dma_start ? 1'b1 : 1'b0; membr_state <= dma_start ? MEMBR_MODE : MEMBR_IDLE; membr_done <= 1'b0; membr_state <= dma_start & membr_is_set ? MEMBR_LOADDDR : dma_start ? MEMBR_MODE : MEMBR_IDLE; end MEMBR_MODE: begin Loading @@ -306,6 +334,7 @@ always @ (posedge clk) membr_addr <= 16'h207; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_MODE : MEMBR_WIDTH; end MEMBR_WIDTH: Loading @@ -314,6 +343,7 @@ always @ (posedge clk) membr_addr <= 16'h206; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_WIDTH : MEMBR_LEN; end MEMBR_LEN: Loading @@ -322,6 +352,7 @@ always @ (posedge clk) membr_addr <= 16'h205; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_LEN : MEMBR_START; end MEMBR_START: Loading @@ -330,6 +361,7 @@ always @ (posedge clk) membr_addr <= 16'h204; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_START : MEMBR_SIZE; end MEMBR_SIZE: Loading @@ -338,14 +370,16 @@ always @ (posedge clk) membr_addr <= 16'h203; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_SIZE : MEMBR_LOADDR; end MEMBR_LOADDR: begin membr_data <= mem[32*5-1:32*4]; membr_data <= cmd_addr_r; membr_addr <= 16'h202; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_LOADDR : MEMBR_CTRL; end MEMBR_CTRL: Loading @@ -354,6 +388,7 @@ always @ (posedge clk) membr_addr <= 16'h200; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= 1'b0; membr_done <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_state <= membr_inprocess | membr_setup ? MEMBR_CTRL : MEMBR_IDLE; end default: Loading @@ -362,6 +397,7 @@ always @ (posedge clk) membr_addr <= 16'h0; membr_start <= 1'b0; membr_setup <= 1'b0; membr_done <= 1'b0; membr_state <= MEMBR_IDLE; end endcase Loading @@ -386,7 +422,6 @@ assign cmd_stb = out_stb; always @ (posedge clk) if (rst) begin membr_done <= 1'b0; state <= STATE_IDLE; out_ad <= 8'h0; out_stb <= 1'b0; Loading @@ -395,56 +430,48 @@ always @ (posedge clk) case (state) STATE_IDLE: begin membr_done <= 1'b0; out_ad <= 8'h0; out_stb <= 1'b0; state <= membr_setup ? STATE_CMD_0 : STATE_IDLE; end STATE_CMD_0: begin membr_done <= 1'b0; out_ad <= membr_addr[7:0]; out_stb <= 1'b1; state <= STATE_CMD_1; end STATE_CMD_1: begin membr_done <= 1'b0; out_ad <= membr_addr[15:8]; out_stb <= 1'b0; state <= STATE_DATA_0; end STATE_DATA_0: begin membr_done <= 1'b0; out_ad <= membr_data[7:0]; out_stb <= 1'b0; state <= STATE_DATA_1; end STATE_DATA_1: begin membr_done <= 1'b0; out_ad <= membr_data[15:8]; out_stb <= 1'b0; state <= STATE_DATA_2; end STATE_DATA_2: begin membr_done <= 1'b0; out_ad <= membr_data[23:16]; out_stb <= 1'b0; state <= STATE_DATA_3; end STATE_DATA_3: begin membr_done <= 1'b0; out_ad <= membr_data[31:24]; out_stb <= 1'b0; state <= STATE_IDLE; end default: begin membr_done <= 1'b1; out_ad <= 8'hff; out_stb <= 1'b0; state <= STATE_IDLE; Loading Loading
dma_adapter.v +121 −94 Original line number Diff line number Diff line Loading @@ -29,26 +29,13 @@ * a big dma data storage and axi interface. So it shall recieve data and control * for 1 burst and pass it to axi. */ /* * For debug only: * DMA write: * 0x0c: |mem[:] => use dbg registers as a source of dma data * 0x10: addr of the buffer * 0x14: size * 0x18: burst len * 0x1c: start dma * 0x20-0x3c - data */ module send_dma #( parameter REGISTERS_CNT = 20 ) ( input wire clk, input wire rst, // dbg iface input wire [32*REGISTERS_CNT - 1:0] mem, input wire dbg_mode, output wire clrstart, // cmd iface input wire cmd_type, // 1 = wr, 0 = rd input wire cmd_val, // issue a cmd Loading @@ -57,9 +44,11 @@ module send_dma #( // data iface input wire [63:0] wr_data_in, output wire wr_val_out, input wire wr_val_in, output wire wr_ack_out, output wire [63:0] rd_data_out, input wire rd_val_in, output wire rd_val_out, input wire rd_ack_in, // membridge iface output wire [7:0] cmd_ad, Loading Loading @@ -89,91 +78,133 @@ module send_dma #( // if not busy and got cmd with val => cmd recieved, assert busy, start a respective algorithm wire wr_start; wire rd_start; wire dma_start; reg wr_done; reg rd_done; reg cmd_type_r; reg cmd_addr_r; reg cmd_val_r; reg [31:7] cmd_addr_r; reg cmd_busy_r; wire set_busy; wire clr_busy; assign set_busy = ~cmd_busy_r & cmd_val; assign clr_busy = cmd_busy_r & (wr_done | rd_done) assign clr_busy = cmd_busy_r & (wr_done | rd_done); assign cmd_busy = cmd_busy_r; assign wr_start = set_busy & cmd_type; assign rd_start = set_busy & ~cmd_type; always @ (posedge clk) begin cmd_type_r <= rst ? 1'b0 : cmd_addr_r <= rst ? 1'b0 : cmd_val_r <= rst ? 1'b0 : cmd_busy_r <= rst ? 1'b0 : ~cmd_busy_r & cmd_val_r cmd_type_r <= rst ? 1'b0 : set_busy ? cmd_type : cmd_type_r; cmd_addr_r <= rst ? 1'b0 : set_busy ? cmd_addr : cmd_addr_r; cmd_busy_r <= (cmd_busy_r | set_busy) & ~rst & ~clr_busy; end /* * Read/write state machine * Read/write data state machine * For better readability the state machine is splitted to two pieces: * the first one is responsible only for the CMD WRITE case handling, * the second one, respectively, for CMD READ * * Each fsm starts a membridge fsm, which, if being 1st time launched, sets up * membridge's registers, or, if have been launched before, just programs read/write * Simultaniously with each fsm starts a membridge fsm, which, if being 1st time launched, * sets up membridge's registers, or, if have been launched before, just programs read/write * address. * * Current implementation is extremely slow, but simple and reliable * After all other parts are implemented and this place occurs to be a bottleneck * then replace it (and may be membridge too) with something more ... pipelined */ reg [1:0] rdwr_state; // check if memberidge was already set up reg membr_is_set; always @ (posedge clk) membr_is_set <= (membr_is_set | dma_start) & ~rst; // common state register reg [3:0] rdwr_state; // Get data from buffer localparam READ_IDLE = 0; localparam READ_ON = 2; localparam READ_DATA = 3; localparam READ_WAIT_ADDR = 3; localparam READ_DATA = 4; reg rd_reset_page; reg rd_next_page; reg rd_data reg rd_data; reg [6:0] rd_data_count; wire rd_stop; wire rd_cnt_to_pull; assign rd_cnt_to_pull == 7'hf; assign rd_stop = rd_ack_in & rd_data_count == rd_cnt_to_pull; assign rd_data_out = rd_data; always @ (posedge clk) if (rst) begin rd_state <= READ_IDLE; rd_done <= rdwr_state <= READ_IDLE; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_en <= 1'b0; end else case (rst) READ_IDLE: begin rdwr_state <= rd_start ? READ_WAIT_ADDR : READ_IDLE; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_en <= 1'b0; end READ_ON: READ_WAIT_ADDR: // wait until address information is sent to the bus and input buffer got data begin rdwr_state <= membr_state == IDLE & rdata_done ? READ_DATA : READ_WAIT_ADDR; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_en <= 1'b0; end READ_DATA: begin rdwr_state <= rd_stop ? READ_IDLE : READ_DATA; rd_done <= rd_stop ? 1'b1 : 1'b0; rd_data_count <= rd_ack_in ? rd_data_count + 1'b1 : rd_data_count; rd_next_page <= rd_stop ? 1'b1 : 1'b0; rd_en <= rd_ack_in ? 1'b1 : 1'b0; end default: // write is processing begin rdwr_state <= READ_IDLE; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_en <= 1'b0; end // Put data into buffer localparam WRITE_IDLE = 0; localparam WRITE_ON = 1; localparam WRITE_DATA = 1; localparam WRITE_WAIT_ADDR = 2; reg wr_en; reg wr_reset_page; reg wr_next_page; reg [63:0] wr_data; reg [6:0] wr_page_offset; reg [6:0] wr_data_count; reg wr_page_ready; reg wr_val; wire [31:0] dw0 = mem[32*9-1:32*8]; wire [31:0] dw1 = mem[32*10-1:32*9]; wire [31:0] dw2 = mem[32*11-1:32*10]; wire [31:0] dw3 = mem[32*12-1:32*11]; wire [6:0] wr_cnt_to_push; wire wr_stop; assign wr_cnt_to_push = 7'hf; assign wr_stop = wr_page_offset == wr_cnt_to_push; assign wr_stop = wr_val_in & wr_data_count == wr_cnt_to_push; assign wr_val_in = wr_val; assign wr_ack_out = wr_val_in & rdwr_state == WRITE_DATA; assign wr_data_in = wr_data; Loading @@ -182,7 +213,7 @@ always @ (posedge clk) if (rst) begin wr_done <= 1'b0; wr_page_offset <= 7'd0; wr_data_count <= 7'd0; wr_val <= 1'b0; wr_data <= 64'h0; wr_next_page <= 1'b0; Loading @@ -195,37 +226,42 @@ always @ (posedge clk) case (wr_state) WRITE_IDLE: begin wr_page_offset <= 7'd0; wr_data_count <= 7'd0; wr_done <= 1'b0; wr_val <= 1'b0; wr_data <= 64'h0; wr_next_page <= 1'b0; wr_reset_page <= wr_start ? 1'b1 : 1'b0; wr_en <= 1'b0; wr_page_ready <= 1'b0; rdwr_state <= wr_start ? WRITE_ON : WRITE_IDLE; rdwr_state <= wr_start ? WRITE_DATA : WRITE_IDLE; end WRITE_ON: WRITE_DATA: begin wr_done <= wr_stop ? 1'b1 : 1'b0; wr_page_offset <= wr_page_offset + 1'b1; wr_val <= 1'b1; wr_data <= ~dbg_mode ? in_data : wr_page_offset[1:0] == 2'b00 ? {dw0, 25'h0, wr_page_offset} : wr_page_offset[1:0] == 2'b01 ? {dw1, 25'h0, wr_page_offset} : wr_page_offset[1:0] == 2'b10 ? {dw2, 25'h0, wr_page_offset} : {dw3, 25'h0, wr_page_offset}; wr_done <= wr_stop & membr_state == IDLE ? 1'b1 : 1'b0; wr_data_count <= wr_val_in ? wr_data_count + 1'b1 : wr_data_count; wr_data <= in_data : wr_next_page <= wr_stop ? 1'b1 : 1'b0; wr_reset_page <= 1'b0; wr_en <= 1'b1; wr_en <= wr_val_in; wr_page_ready <= wr_stop ? 1'b1 : 1'b0; rdwr_state <= wr_stop ? WRITE_IDLE : WRITE_ON; rdwr_state <= wr_stop & membr_state == IDLE ? WRITE_IDLE : wr_stop ? WRITE_WAIT_ADDR : WRITE_DATA; end WRITE_WAIT_ADDR: // in case all data is written into a buffer, but address is still being issued on axi bus begin wr_done <= membr_state == IDLE ? 1'b1 : 1'b0; wr_data_count <= 7'd0; wr_data <= 64'h0; wr_next_page <= 1'b0; wr_reset_page <= 1'b0; wr_en <= 1'b0; wr_page_ready <= 1'b0; rdwr_state <= membr_state == IDLE ? WRITE_IDLE : WRITE_WAIT_ADDR; end default: // read is executed begin wr_done <= 1'b0; wr_page_offset <= 7'd0; wr_val <= 1'b0; wr_data_count <= 7'd0; wr_data <= 64'h0; wr_next_page <= 1'b0; wr_reset_page <= 1'b0; Loading @@ -235,13 +271,12 @@ always @ (posedge clk) end endcase // temporary assigments // membridge interface assigments assign status_start = 1'b0; // no need until status is used assign cmd_wrmem = 1'b0; // for now only writing assign xfer_reset_page_wr = 1'b0; // for now only writing assign buf_rpage_nxt = 1'b0; // for now only writing assign buf_rd = 1'b0; // for now only writing assign xfer_reset_page_wr = 1'b0; assign cmd_wrmem = ~cmd_type_r; assign xfer_reset_page_wr = rd_reset_page; assign buf_rpage_nxt = rd_next_page; assign buf_rd = rd_en; assign buf_wdata = wr_data; assign buf_wr = wr_en; assign buf_wpage_nxt = wr_next_page; Loading @@ -249,16 +284,9 @@ assign xfer_reset_page_rd = wr_reset_page; assign page_ready_chn = cmd_wrmem ? 1'b0 : wr_page_ready; assign frame_done_chn = 1'b1; // compute membridge parameters to corresponding mem register // dma fsm // mode = 0 // width = 4 // size = 0x14 // start = 0 // lo_address = 0x10 // ctrl = 0x1c // len = 0x18 /* * Transfer address and membridge set-ups state machine */ localparam MEMBR_IDLE = 0; localparam MEMBR_MODE = 1; localparam MEMBR_WIDTH = 2; Loading @@ -275,11 +303,8 @@ reg membr_done; reg [2:0] membr_state; reg membr_setup; // indicates the first tick of the state wire membr_inprocess; wire dma_start; assign dma_start = |mem[32*8-1:32*7]; assign clrstart = dma_start & membr_state == MEMBR_IDLE; //assign wr_start = membr_state == MEMBR_CTRL; assign dma_start = wr_start | rd_start; always @ (posedge clk) if (rst) Loading @@ -288,6 +313,7 @@ always @ (posedge clk) membr_addr <= 16'h0; membr_start <= 1'b0; membr_setup <= 1'b0; membr_done <= 1'b0; membr_state <= MEMBR_IDLE; end else Loading @@ -298,7 +324,9 @@ always @ (posedge clk) membr_addr <= 16'h200; membr_start <= dma_start ? 1'b1 : 1'b0; membr_setup <= dma_start ? 1'b1 : 1'b0; membr_state <= dma_start ? MEMBR_MODE : MEMBR_IDLE; membr_done <= 1'b0; membr_state <= dma_start & membr_is_set ? MEMBR_LOADDDR : dma_start ? MEMBR_MODE : MEMBR_IDLE; end MEMBR_MODE: begin Loading @@ -306,6 +334,7 @@ always @ (posedge clk) membr_addr <= 16'h207; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_MODE : MEMBR_WIDTH; end MEMBR_WIDTH: Loading @@ -314,6 +343,7 @@ always @ (posedge clk) membr_addr <= 16'h206; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_WIDTH : MEMBR_LEN; end MEMBR_LEN: Loading @@ -322,6 +352,7 @@ always @ (posedge clk) membr_addr <= 16'h205; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_LEN : MEMBR_START; end MEMBR_START: Loading @@ -330,6 +361,7 @@ always @ (posedge clk) membr_addr <= 16'h204; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_START : MEMBR_SIZE; end MEMBR_SIZE: Loading @@ -338,14 +370,16 @@ always @ (posedge clk) membr_addr <= 16'h203; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_SIZE : MEMBR_LOADDR; end MEMBR_LOADDR: begin membr_data <= mem[32*5-1:32*4]; membr_data <= cmd_addr_r; membr_addr <= 16'h202; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_done <= 1'b0; membr_state <= membr_inprocess | membr_setup ? MEMBR_LOADDR : MEMBR_CTRL; end MEMBR_CTRL: Loading @@ -354,6 +388,7 @@ always @ (posedge clk) membr_addr <= 16'h200; membr_start <= membr_inprocess ? 1'b0 : 1'b1; membr_setup <= 1'b0; membr_done <= membr_inprocess | membr_setup ? 1'b0 : 1'b1; membr_state <= membr_inprocess | membr_setup ? MEMBR_CTRL : MEMBR_IDLE; end default: Loading @@ -362,6 +397,7 @@ always @ (posedge clk) membr_addr <= 16'h0; membr_start <= 1'b0; membr_setup <= 1'b0; membr_done <= 1'b0; membr_state <= MEMBR_IDLE; end endcase Loading @@ -386,7 +422,6 @@ assign cmd_stb = out_stb; always @ (posedge clk) if (rst) begin membr_done <= 1'b0; state <= STATE_IDLE; out_ad <= 8'h0; out_stb <= 1'b0; Loading @@ -395,56 +430,48 @@ always @ (posedge clk) case (state) STATE_IDLE: begin membr_done <= 1'b0; out_ad <= 8'h0; out_stb <= 1'b0; state <= membr_setup ? STATE_CMD_0 : STATE_IDLE; end STATE_CMD_0: begin membr_done <= 1'b0; out_ad <= membr_addr[7:0]; out_stb <= 1'b1; state <= STATE_CMD_1; end STATE_CMD_1: begin membr_done <= 1'b0; out_ad <= membr_addr[15:8]; out_stb <= 1'b0; state <= STATE_DATA_0; end STATE_DATA_0: begin membr_done <= 1'b0; out_ad <= membr_data[7:0]; out_stb <= 1'b0; state <= STATE_DATA_1; end STATE_DATA_1: begin membr_done <= 1'b0; out_ad <= membr_data[15:8]; out_stb <= 1'b0; state <= STATE_DATA_2; end STATE_DATA_2: begin membr_done <= 1'b0; out_ad <= membr_data[23:16]; out_stb <= 1'b0; state <= STATE_DATA_3; end STATE_DATA_3: begin membr_done <= 1'b0; out_ad <= membr_data[31:24]; out_stb <= 1'b0; state <= STATE_IDLE; end default: begin membr_done <= 1'b1; out_ad <= 8'hff; out_stb <= 1'b0; state <= STATE_IDLE; Loading