Loading axi_regs.v +15 −74 Original line number Original line Diff line number Diff line Loading @@ -2,7 +2,7 @@ * Module: axi_regs * Module: axi_regs * Date: 2015-07-11 * Date: 2015-07-11 * Author: Alexey * Author: Alexey * Description: temporary registers, connected to axi bus * Description: slave axi interface buffer * * * Copyright (c) 2015 Elphel, Inc. * Copyright (c) 2015 Elphel, Inc. * axi_regs.v is free software; you can redistribute it and/or modify * axi_regs.v is free software; you can redistribute it and/or modify Loading @@ -18,33 +18,12 @@ * You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ *******************************************************************************/ /* * Some common formulas for AXI: * // - integer division, % - leftover * addr = raddr(waddr) % device_memory_size * size = arsize(awsize), size_bytes = 2^size, bus_width = log2(bus_width_bytes), * bus_offset = addr % bus_width_bytes, aligned_bus_addr - address of the first byte on a bus * word_addr - current memory word's index, word_size_bytes - memory word size * For the i-th byte on a bus, * -------burst_cnt = 0: * aligned_bus_addr = addr // bus_width_bytes * bus_width_bytes * word_addr[i] = (aligned_bus_addr + i) // word_size_bytes * word_data[i] = mem[word_addr[i]] * >data[i] = word_data[i][i % word_size] * >atrobe[i] = i[bus_width:size] == bus_offset[bus_width:size] & i[size-1:0] >= bus_offset[size-1:0] * -------burst_cnt > 0: * let addr_-1 be an addr of a last burst * Incremental * addr = addr_-1 // size_bytes * size_bytes + size_bytes * * Wrapping * addr = addr_-1 // size_bytes * size_bytes + size_bytes */ `include "axibram_read.v" `include "axibram_read.v" `include "axibram_write.v" `include "axibram_write.v" `include "membridge.v" module axi_regs #( module axi_regs( parameter REGISTERS_CNT = 20 ) ( input wire ACLK, // AXI PS Master GP1 Clock , input input wire ACLK, // AXI PS Master GP1 Clock , input input wire ARESETN, // AXI PS Master GP1 Reset, output input wire ARESETN, // AXI PS Master GP1 Reset, output // AXI PS Master GP1: Read Address // AXI PS Master GP1: Read Address Loading Loading @@ -90,57 +69,19 @@ module axi_regs( input wire BREADY, // AXI PS Master GP1 BREADY, output input wire BREADY, // AXI PS Master GP1 BREADY, output output wire [11:0] BID, // AXI PS Master GP1 BID[11:0], input output wire [11:0] BID, // AXI PS Master GP1 BID[11:0], input output wire [1:0] BRESP, // AXI PS Master GP1 BRESP[1:0], input output wire [1:0] BRESP, // AXI PS Master GP1 BRESP[1:0], input // registers iface input wire [31:0] bram_rdata, output wire [31:0] bram_waddr, output wire [31:0] bram_wdata, output wire [31:0] bram_raddr, output wire [3:0] bram_wstb, output wire bram_wen, output wire bram_ren, output wire bram_regen ); ); // register set //reg [31:0] mem [3:0]; /* /* * DMA write: * Converntional MAXI interface from x393 project * 0x10: addr of the buffer * 0x14: size * 0x18: burst len * 0x1c: * 0x20-0x3c - data */ */ reg [32*REGISTERS_CNT - 1:0] mem; /* * Converntional MAXI interface from x393 project, uses fifos, writes to/reads from memory */ wire [31:0] bram_waddr; wire [31:0] bram_raddr; wire [31:0] bram_wdata; wire [31:0] bram_rdata; wire [3:0] bram_wstb; wire bram_wen; wire bram_ren; wire bram_regen; // 'write into memory' // for testing purposes the 'memory' is a set of registers for now // later on will try to use them as an application level registers genvar ii; generate for (ii = 0; ii < REGISTERS_CNT; ii = ii + 1) begin: write_to_mem always @ (posedge ACLK) begin mem[32*ii + 31-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[31-:8] & {8{bram_wstb[3]}}: mem[32*ii + 31-:8]; mem[32*ii + 23-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[23-:8] & {8{bram_wstb[2]}}: mem[32*ii + 23-:8]; mem[32*ii + 15-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[15-:8] & {8{bram_wstb[1]}}: mem[32*ii + 15-:8]; mem[32*ii + 7-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[ 7-:8] & {8{bram_wstb[0]}}: mem[32*ii + 7-:8]; end end endgenerate // read from memory. Interface's protocol assumes returning data to delay reg [3:0] bram_raddr_r; reg [31:0] bram_rdata_r; always @ (posedge ACLK) begin bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r; bram_rdata_r <= bram_regen ? mem[32*bram_raddr_r + 31-:32] : bram_rdata_r; end assign bram_rdata = bram_rdata_r; // Interface's instantiation // Interface's instantiation axibram_write #( axibram_write #( .ADDRESS_BITS(16) .ADDRESS_BITS(16) Loading dma_adapter.v +43 −41 Original line number Original line Diff line number Diff line Loading @@ -129,11 +129,12 @@ reg rd_reset_page; reg rd_next_page; reg rd_next_page; reg rd_data; reg rd_data; reg [6:0] rd_data_count; reg [6:0] rd_data_count; reg rd_en; wire rd_stop; wire rd_stop; wire rd_cnt_to_pull; wire rd_cnt_to_pull; assign rd_cnt_to_pull == 7'hf; assign rd_cnt_to_pull = 7'hf; assign rd_stop = rd_ack_in & rd_data_count == rd_cnt_to_pull; assign rd_stop = rd_ack_in & rd_data_count == rd_cnt_to_pull; assign rd_data_out = rd_data; assign rd_data_out = rd_data; Loading @@ -148,7 +149,7 @@ always @ (posedge clk) rd_en <= 1'b0; rd_en <= 1'b0; end end else else case (rst) case (rdwr_state) READ_IDLE: READ_IDLE: begin begin rdwr_state <= rd_start ? READ_WAIT_ADDR : READ_IDLE; rdwr_state <= rd_start ? READ_WAIT_ADDR : READ_IDLE; Loading @@ -159,7 +160,7 @@ always @ (posedge clk) end end READ_WAIT_ADDR: // wait until address information is sent to the bus and input buffer got data READ_WAIT_ADDR: // wait until address information is sent to the bus and input buffer got data begin begin rdwr_state <= membr_state == IDLE & rdata_done ? READ_DATA : READ_WAIT_ADDR; rdwr_state <= membr_state == READ_IDLE & rdata_done ? READ_DATA : READ_WAIT_ADDR; rd_done <= 1'b0; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_next_page <= 1'b0; Loading @@ -181,6 +182,7 @@ always @ (posedge clk) rd_next_page <= 1'b0; rd_next_page <= 1'b0; rd_en <= 1'b0; rd_en <= 1'b0; end end endcase // Put data into buffer // Put data into buffer Loading Loading @@ -220,7 +222,7 @@ always @ (posedge clk) rdwr_state <= WRITE_IDLE; rdwr_state <= WRITE_IDLE; end end else else case (wr_state) case (rdwr_state) WRITE_IDLE: WRITE_IDLE: begin begin wr_data_count <= 7'd0; wr_data_count <= 7'd0; Loading @@ -234,26 +236,26 @@ always @ (posedge clk) end end WRITE_DATA: WRITE_DATA: begin begin wr_done <= wr_stop & membr_state == IDLE ? 1'b1 : 1'b0; wr_done <= wr_stop & membr_state == WRITE_IDLE ? 1'b1 : 1'b0; wr_data_count <= wr_val_in ? wr_data_count + 1'b1 : wr_data_count; wr_data_count <= wr_val_in ? wr_data_count + 1'b1 : wr_data_count; wr_data <= in_data : wr_data <= wr_data_in; wr_next_page <= wr_stop ? 1'b1 : 1'b0; wr_next_page <= wr_stop ? 1'b1 : 1'b0; wr_reset_page <= 1'b0; wr_reset_page <= 1'b0; wr_en <= wr_val_in; wr_en <= wr_val_in; wr_page_ready <= wr_stop ? 1'b1 : 1'b0; wr_page_ready <= wr_stop ? 1'b1 : 1'b0; rdwr_state <= wr_stop & membr_state == IDLE ? WRITE_IDLE : rdwr_state <= wr_stop & membr_state == WRITE_IDLE ? WRITE_IDLE : wr_stop ? WRITE_WAIT_ADDR : WRITE_DATA; wr_stop ? WRITE_WAIT_ADDR : WRITE_DATA; end end WRITE_WAIT_ADDR: // in case all data is written into a buffer, but address is still being issued on axi bus WRITE_WAIT_ADDR: // in case all data is written into a buffer, but address is still being issued on axi bus begin begin wr_done <= membr_state == IDLE ? 1'b1 : 1'b0; wr_done <= membr_state == WRITE_IDLE ? 1'b1 : 1'b0; wr_data_count <= 7'd0; wr_data_count <= 7'd0; wr_data <= 64'h0; wr_data <= 64'h0; wr_next_page <= 1'b0; wr_next_page <= 1'b0; wr_reset_page <= 1'b0; wr_reset_page <= 1'b0; wr_en <= 1'b0; wr_en <= 1'b0; wr_page_ready <= 1'b0; wr_page_ready <= 1'b0; rdwr_state <= membr_state == IDLE ? WRITE_IDLE : WRITE_WAIT_ADDR; rdwr_state <= membr_state == WRITE_IDLE ? WRITE_IDLE : WRITE_WAIT_ADDR; end end default: // read is executed default: // read is executed begin begin Loading Loading @@ -322,7 +324,7 @@ always @ (posedge clk) membr_start <= dma_start ? 1'b1 : 1'b0; membr_start <= dma_start ? 1'b1 : 1'b0; membr_setup <= dma_start ? 1'b1 : 1'b0; membr_setup <= dma_start ? 1'b1 : 1'b0; membr_done <= 1'b0; membr_done <= 1'b0; membr_state <= dma_start & membr_is_set ? MEMBR_LOADDDR : membr_state <= dma_start & membr_is_set ? MEMBR_LOADDR : dma_start ? MEMBR_MODE : MEMBR_IDLE; dma_start ? MEMBR_MODE : MEMBR_IDLE; end end MEMBR_MODE: MEMBR_MODE: Loading dma_control.v +206 −43 Original line number Original line Diff line number Diff line Loading @@ -19,8 +19,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/> . * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ *******************************************************************************/ /* /* * Later on most of address evaluation logic could divided into 2 parts, which * Later on most of address evaluation logic could be divided into 2 parts, which * could be presented as 2 instances of 1 parameterized module * could be presented as 2 instances of 1 parameterized module * + split data and address parts. Didnt do that because not sure if * virtual channels would be implemented in the future */ */ module dma_control( module dma_control( input wire sclk, // sata clock input wire sclk, // sata clock Loading @@ -35,6 +37,19 @@ input wire dma_start, input wire dma_start, output wire dma_done, output wire dma_done, // adapter command iface input wire adp_busy, output wire [31:7] adp_addr, output wire adp_type, output wire adp_val, // sata host command iface input wire host_ready_for_cmd, output wire host_new_cmd, output wire [1:0] host_cmd_type, output wire [31:0] host_sector_count, output wire [31:0] host_sector_addr, // adapter data iface // adapter data iface // to main memory // to main memory output wire [63:0] to_data, output wire [63:0] to_data, Loading @@ -43,7 +58,7 @@ // from main memory // from main memory input wire [63:0] from_data, input wire [63:0] from_data, input wire from_val, input wire from_val, input wire from_ack output wire from_ack, // sata host iface // sata host iface // data from sata host // data from sata host Loading @@ -55,7 +70,156 @@ output wire out_val, output wire out_val, input wire out_busy input wire out_busy ); ); ////////////////////////////////////////////////////////////////////////////////////// //// ADDRESS ////////////////////////////////////////////////////////////////////////////////////// wire dma_done_adp; wire dma_done_host; assign dma_done = dma_done_host & dma_done_adp; reg adp_busy_sclk; /* * Commands to sata host fsm */ // for now only 2 states: idle and send a pulse reg host_issued; wire host_issued_set; wire host_issued_clr; assign dma_done_host = host_issued; assign host_issued_set = ~adp_busy_sclk & host_ready_for_cmd & dma_start; assign host_issued_clr = dma_done; always @ (posedge sclk) host_issued <= (host_issued | host_issued_set) & ~host_issued_clr & ~rst; // drive iface signals assign host_new_cmd = host_issued_set; assign host_cmd_type = dma_type; assign host_sector_count = sector_cnt; assign host_sector_addr = lba; /* * Commands to adapter fsm */ reg [33:0] quarter_sector_cnt; wire last_data; // last 128 bytes of data are transmitted now wire adp_val_sclk; reg [31:7] current_addr; reg current_type; // synchronize with host fsm reg adp_done; wire adp_done_clr; wire adp_done_set; assign dma_done_adp = adp_done; assign adp_done_set = state_wait_done & clr_wait_done & ~set_wait_busy; // = state_wait_done & set_idle; assign adp_done_clr = dma_done; always @ (posedge sclk) adp_done <= (adp_done | adp_done_set) & ~adp_done_clr & ~rst; // calculate sent sector count // 1 sector = 512 bytes for now => 1 quarter_sector = 128 bytes always @ (posedge sclk) quarter_sector_cnt <= ~set_wait_busy ? quarter_sector_cnt : state_idle ? 34'h0 : // new dma request quarter_sector_cnt + 1'b1; // same dma request, next 128 bytes // flags if we're currently sending the last data piece of dma transaction assign last_data = (sector_cnt == quarter_sector_cnt[33:2] + 1'b1) & (&quarter_sector_cnt[1:0]); // calculate outgoing address // increment every transaction to adapter always @ (posedge sclk) current_addr <= ~set_wait_busy ? current_addr : state_idle ? mem_address : // new dma request current_addr + 1'b1; // same dma request, next 128 bytes always @ (posedge sclk) current_type <= ~set_wait_busy ? current_type : state_idle ? dma_type : // new dma request current_type; // same dma request, next 128 bytes // fsm itself wire state_idle; reg state_wait_busy; reg state_wait_done; wire set_wait_busy; wire set_wait_done; wire clr_wait_busy; wire clr_wait_done; assign set_wait_busy = state_idle & host_issued_set // same start pulse for both fsms | state_wait_done & clr_wait_done & ~last_data; // still have some data to transmit within a current dma request assign set_wait_done = state_wait_busy & clr_wait_busy; assign clr_wait_busy = adp_busy_sclk; assign clr_wait_done = ~adp_busy_sclk; assign state_idle = ~state_wait_busy & ~state_wait_done; always @ (posedge sclk) begin state_wait_busy <= (state_wait_busy | set_wait_busy) & ~clr_wait_busy & ~rst; state_wait_done <= (state_wait_done | set_wait_done) & ~clr_wait_done & ~rst; end // conrol signals resync reg adp_val_r; reg adp_val_rr; always @ (posedge hclk) begin adp_val_r <= adp_val_sclk; adp_val_rr <= adp_val_r; end assign adp_addr = current_addr; assign adp_type = current_type; assign adp_val = adp_val_rr; // Maintaining correct adp_busy level @ sclk // assuming busy won't toggle rapidly, can afford not implementing handshakes wire adp_busy_sclk_set; wire adp_busy_sclk_clr; wire adp_busy_set; wire adp_busy_clr; reg adp_busy_r; assign adp_busy_set = adp_busy & ~adp_busy_r; assign adp_busy_clr = ~adp_busy & adp_busy_r; always @ (posedge sclk) adp_busy_sclk <= (adp_busy_sclk | adp_busy_sclk_set) & ~rst & ~adp_busy_sclk_clr; always @ (posedge hclk) adp_busy_r <= adp_busy; pulse_cross_clock adp_busy_set_pulse( .rst (rst), .src_clk (hclk), .dst_clk (sclk), .in_pulse (adp_busy_set), .out_pulse (adp_busy_sclk_set), .busy () ); pulse_cross_clock adp_busy_clr_pulse( .rst (rst), .src_clk (hclk), .dst_clk (sclk), .in_pulse (adp_busy_clr), .out_pulse (adp_busy_sclk_clr), .busy () ); ////////////////////////////////////////////////////////////////////////////////////// //// DATA ////////////////////////////////////////////////////////////////////////////////////// /* /* * from main memory resyncronisation circuit * from main memory resyncronisation circuit */ */ Loading @@ -65,8 +229,8 @@ reg [8:0] from_wr_addr; wire [8:0] from_wr_next_addr; wire [8:0] from_wr_next_addr; wire [9:0] from_rd_next_addr; wire [9:0] from_rd_next_addr; // gray coded addresses // gray coded addresses reg [9:0] from_rd_addr; reg [9:0] from_rd_addr_gr; reg [8:0] from_wr_addr; reg [8:0] from_wr_addr_gr; // anti-metastability shift registers for gray-coded addresses // anti-metastability shift registers for gray-coded addresses reg [9:0] from_rd_addr_gr_r; reg [9:0] from_rd_addr_gr_r; reg [8:0] from_wr_addr_gr_r; reg [8:0] from_wr_addr_gr_r; Loading Loading @@ -99,13 +263,13 @@ end always @ (posedge sclk) always @ (posedge sclk) begin begin from_wr_addr_gr_r <= rst ? 9'h0 : from_wr_addr; from_wr_addr_gr_r <= rst ? 9'h0 : from_wr_addr; from_wr_addr_gr_rr <= rst ? 9'h0 : from_wr_addr_rr; from_wr_addr_gr_rr <= rst ? 9'h0 : from_wr_addr_gr_r; end end // read address -> hclk (wr) domain to compare // read address -> hclk (wr) domain to compare always @ (posedge hclk) always @ (posedge hclk) begin begin from_rd_addr_gr_r <= rst ? 10'h0 : from_rd_addr; from_rd_addr_gr_r <= rst ? 10'h0 : from_rd_addr; from_rd_addr_gr_rr <= rst ? 10'h0 : from_rd_addr_rr; from_rd_addr_gr_rr <= rst ? 10'h0 : from_rd_addr_gr_r; end end // translate resynced write address into ordinary (non-gray) address // translate resynced write address into ordinary (non-gray) address genvar ii; genvar ii; Loading Loading @@ -169,8 +333,8 @@ reg [9:0] to_wr_addr; wire [9:0] to_wr_next_addr; wire [9:0] to_wr_next_addr; wire [8:0] to_rd_next_addr; wire [8:0] to_rd_next_addr; // gray coded addresses // gray coded addresses reg [8:0] to_rd_addr; reg [8:0] to_rd_addr_gr; reg [9:0] to_wr_addr; reg [9:0] to_wr_addr_gr; // anti-metastability shift registers for gray-coded addresses // anti-metastability shift registers for gray-coded addresses reg [8:0] to_rd_addr_gr_r; reg [8:0] to_rd_addr_gr_r; reg [9:0] to_wr_addr_gr_r; reg [9:0] to_wr_addr_gr_r; Loading Loading @@ -204,16 +368,15 @@ end always @ (posedge hclk) always @ (posedge hclk) begin begin to_wr_addr_gr_r <= rst ? 10'h0 : to_wr_addr; to_wr_addr_gr_r <= rst ? 10'h0 : to_wr_addr; to_wr_addr_gr_rr <= rst ? 10'h0 : to_wr_addr_rr; to_wr_addr_gr_rr <= rst ? 10'h0 : to_wr_addr_gr_r; end end // read address -> sclk (wr) domain to compare // read address -> sclk (wr) domain to compare always @ (posedge sclk) always @ (posedge sclk) begin begin to_rd_addr_gr_r <= rst ? 9'h0 : to_rd_addr; to_rd_addr_gr_r <= rst ? 9'h0 : to_rd_addr; to_rd_addr_gr_rr <= rst ? 9'h0 : to_rd_addr_rr; to_rd_addr_gr_rr <= rst ? 9'h0 : to_rd_addr_gr_r; end end // translate resynced write address into ordinary (non-gray) address // translate resynced write address into ordinary (non-gray) address genvar ii; generate generate for (ii = 0; ii < 10; ii = ii + 1) for (ii = 0; ii < 10; ii = ii + 1) begin: to_wr_antigray begin: to_wr_antigray Loading dma_regs.v 0 → 100644 +152 −0 Original line number Original line Diff line number Diff line /******************************************************************************* * Module: dma_regs * Date: 2015-07-11 * Author: Alexey * Description: temporary registers, connected to axi bus * * Copyright (c) 2015 Elphel, Inc. * dma_regs.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * dma_regs.v file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ module dma_regs #( parameter REGISTERS_CNT = 20 ) ( input wire rst, input wire ACLK, input wire sclk, // registers iface output wire [31:7] mem_address, output wire [31:0] lba, output wire [31:0] sector_cnt, output wire dma_type, output wire dma_start, input wire dma_done, // axi buffer iface output wire [31:0] bram_rdata, input wire [31:0] bram_raddr, input wire [31:0] bram_waddr, input wire [31:0] bram_wdata, input wire [3:0] bram_wstb, input wire bram_wen, input wire bram_ren, input wire bram_regen ); //reg [32*REGISTERS_CNT - 1:0] mem; /* * Converntional MAXI interface from x393 project, uses fifos, writes to/reads from memory */ /* * Temporary mapping: * rw 0x00: dma address (will automatically align to 128-bytes boundary, i.e. [6:0] -> 0 * rw 0x04: lba * rw 0x08: sector count * rw 0x0c: dma type (any(0x0c) => write) * r1c 0x10: writes: dma start (any(0x10) => start) * reads: dma status of last issued transfer (0xffffffff => done) * ro 0x14: dma last issued dma_address */ reg [31:0] reg00; reg [31:0] reg04; reg [31:0] reg08; reg [31:0] reg0c; reg [31:0] reg10; reg [31:0] reg14; wire dma_done_aclk; wire dma_start_aclk; reg dma_issued; wire [31:0] wdata; pulse_cross_clock dma_done_pulse( .rst (rst), .src_clk (sclk), .dst_clk (ACLK), .in_pulse (dma_done), .out_pulse (dma_done_aclk), .busy () ); pulse_cross_clock dma_start_pulse( .rst (rst), .src_clk (ACLK), .dst_clk (sclk), .in_pulse (dma_start_aclk & ~dma_issued), .out_pulse (dma_start), .busy () ); assign dma_start_aclk = bram_wen & (bram_waddr[3:0] == 4'h4) & |wdata; assign wdata = bram_wdata[31:0] & {{8{bram_wstb[3]}}, {8{bram_wstb[2]}}, {8{bram_wstb[1]}}, {8{bram_wstb[0]}}}; always @ (posedge ACLK) dma_issued <= (dma_issued | dma_start_aclk) & ~rst & ~dma_done_aclk; assign mem_address = reg00[31:7]; assign lba = reg04; assign sector_cnt = reg08; assign dma_type = |reg0c; always @ (posedge ACLK) begin reg00 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h0) ? wdata : reg00; reg04 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h1) ? wdata : reg04; reg08 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h2) ? wdata : reg08; reg0c <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h3) ? wdata : reg0c; reg10 <= rst ? 32'h0 : dma_start_aclk ? 32'h0 : dma_done_aclk ? 32'hffffffff : reg10; // status reg reg14 <= rst ? 32'h0 : dma_done_aclk ? reg00 : reg14; end // read from registers. Interface's protocol assumes returning data with a delay reg [3:0] bram_raddr_r; reg [31:0] bram_rdata_r; always @ (posedge ACLK) begin bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r; bram_rdata_r <= ~bram_regen ? bram_rdata_r : bram_raddr_r == 4'h0 ? reg00 : bram_raddr_r == 4'h1 ? reg04 : bram_raddr_r == 4'h2 ? reg08 : bram_raddr_r == 4'h3 ? reg0c : bram_raddr_r == 4'h4 ? reg10 : bram_raddr_r == 4'h5 ? reg14 : 32'hd34db33f; end assign bram_rdata = bram_rdata_r; /* // for testing purposes the 'memory' is a set of registers for now // later on will try to use them as an application level registers genvar ii; generate for (ii = 0; ii < REGISTERS_CNT; ii = ii + 1) begin: write_to_mem always @ (posedge ACLK) begin mem[32*ii + 31-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[31-:8] & {8{bram_wstb[3]}}: mem[32*ii + 31-:8]; mem[32*ii + 23-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[23-:8] & {8{bram_wstb[2]}}: mem[32*ii + 23-:8]; mem[32*ii + 15-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[15-:8] & {8{bram_wstb[1]}}: mem[32*ii + 15-:8]; mem[32*ii + 7-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[ 7-:8] & {8{bram_wstb[0]}}: mem[32*ii + 7-:8]; end end endgenerate // read from memory. Interface's protocol assumes returning data with a delay reg [3:0] bram_raddr_r; reg [31:0] bram_rdata_r; always @ (posedge ACLK) begin bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r; bram_rdata_r <= bram_regen ? mem[32*bram_raddr_r + 31-:32] : bram_rdata_r; end assign bram_rdata = bram_rdata_r; */ endmodule sata_host.v +42 −4 Original line number Original line Diff line number Diff line Loading @@ -40,7 +40,7 @@ module sata_host( input wire data_clk_out, input wire data_clk_out, // timer // timer output wire sata_timer, output wire [31:0] sata_timer, // phy // phy input wire clkin_150, input wire clkin_150, Loading @@ -50,9 +50,47 @@ module sata_host( output wire txp_out, output wire txp_out, output wire txn_out, output wire txn_out, input wire rxp_in, input wire rxp_in, input wire rxn_in input wire rxn_in, ); output wire plllkdet, output wire dcmlocked );/* assign ready_for_cmd = 1'b0; assign sata_core_full = 1'b0; assign sata_dout = 32'b0; assign sata_core_empty = 1'b0; assign sata_timer = 1'b0; assign linkup = 1'b0; assign txp_out = 1'b0; assign txn_out = 1'b0; assign plllkdet = 1'b0; assign dcmlocked = 1'b0;*/ sata_core sata_core( .ready_for_cmd (ready_for_cmd), .new_cmd (new_cmd), .cmd_type (cmd_type), .sector_count (sector_count), .sector_addr (sector_addr), .sata_din (sata_din), .sata_din_we (sata_din_we), .sata_core_full (sata_core_full), .sata_dout (sata_dout), .sata_dout_re (sata_dout_re), .sata_core_empty (sata_core_empty), .SATA_USER_DATA_CLK_IN (data_clk_in), .SATA_USER_DATA_CLK_OUT (data_clk_out), .sata_timer (sata_timer), .CLKIN_150 (clkin_150), .reset (reset), .LINKUP (linkup), .TXP0_OUT (txp_out), .TXN0_OUT (txn_out), .RXP0_IN (rxp_in), .RXN0_IN (rxn_in), .PLLLKDET_OUT_N (plllkdet), .DCMLOCKED_OUT (dcmlocked) ); endmodule endmodule Loading
axi_regs.v +15 −74 Original line number Original line Diff line number Diff line Loading @@ -2,7 +2,7 @@ * Module: axi_regs * Module: axi_regs * Date: 2015-07-11 * Date: 2015-07-11 * Author: Alexey * Author: Alexey * Description: temporary registers, connected to axi bus * Description: slave axi interface buffer * * * Copyright (c) 2015 Elphel, Inc. * Copyright (c) 2015 Elphel, Inc. * axi_regs.v is free software; you can redistribute it and/or modify * axi_regs.v is free software; you can redistribute it and/or modify Loading @@ -18,33 +18,12 @@ * You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ *******************************************************************************/ /* * Some common formulas for AXI: * // - integer division, % - leftover * addr = raddr(waddr) % device_memory_size * size = arsize(awsize), size_bytes = 2^size, bus_width = log2(bus_width_bytes), * bus_offset = addr % bus_width_bytes, aligned_bus_addr - address of the first byte on a bus * word_addr - current memory word's index, word_size_bytes - memory word size * For the i-th byte on a bus, * -------burst_cnt = 0: * aligned_bus_addr = addr // bus_width_bytes * bus_width_bytes * word_addr[i] = (aligned_bus_addr + i) // word_size_bytes * word_data[i] = mem[word_addr[i]] * >data[i] = word_data[i][i % word_size] * >atrobe[i] = i[bus_width:size] == bus_offset[bus_width:size] & i[size-1:0] >= bus_offset[size-1:0] * -------burst_cnt > 0: * let addr_-1 be an addr of a last burst * Incremental * addr = addr_-1 // size_bytes * size_bytes + size_bytes * * Wrapping * addr = addr_-1 // size_bytes * size_bytes + size_bytes */ `include "axibram_read.v" `include "axibram_read.v" `include "axibram_write.v" `include "axibram_write.v" `include "membridge.v" module axi_regs #( module axi_regs( parameter REGISTERS_CNT = 20 ) ( input wire ACLK, // AXI PS Master GP1 Clock , input input wire ACLK, // AXI PS Master GP1 Clock , input input wire ARESETN, // AXI PS Master GP1 Reset, output input wire ARESETN, // AXI PS Master GP1 Reset, output // AXI PS Master GP1: Read Address // AXI PS Master GP1: Read Address Loading Loading @@ -90,57 +69,19 @@ module axi_regs( input wire BREADY, // AXI PS Master GP1 BREADY, output input wire BREADY, // AXI PS Master GP1 BREADY, output output wire [11:0] BID, // AXI PS Master GP1 BID[11:0], input output wire [11:0] BID, // AXI PS Master GP1 BID[11:0], input output wire [1:0] BRESP, // AXI PS Master GP1 BRESP[1:0], input output wire [1:0] BRESP, // AXI PS Master GP1 BRESP[1:0], input // registers iface input wire [31:0] bram_rdata, output wire [31:0] bram_waddr, output wire [31:0] bram_wdata, output wire [31:0] bram_raddr, output wire [3:0] bram_wstb, output wire bram_wen, output wire bram_ren, output wire bram_regen ); ); // register set //reg [31:0] mem [3:0]; /* /* * DMA write: * Converntional MAXI interface from x393 project * 0x10: addr of the buffer * 0x14: size * 0x18: burst len * 0x1c: * 0x20-0x3c - data */ */ reg [32*REGISTERS_CNT - 1:0] mem; /* * Converntional MAXI interface from x393 project, uses fifos, writes to/reads from memory */ wire [31:0] bram_waddr; wire [31:0] bram_raddr; wire [31:0] bram_wdata; wire [31:0] bram_rdata; wire [3:0] bram_wstb; wire bram_wen; wire bram_ren; wire bram_regen; // 'write into memory' // for testing purposes the 'memory' is a set of registers for now // later on will try to use them as an application level registers genvar ii; generate for (ii = 0; ii < REGISTERS_CNT; ii = ii + 1) begin: write_to_mem always @ (posedge ACLK) begin mem[32*ii + 31-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[31-:8] & {8{bram_wstb[3]}}: mem[32*ii + 31-:8]; mem[32*ii + 23-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[23-:8] & {8{bram_wstb[2]}}: mem[32*ii + 23-:8]; mem[32*ii + 15-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[15-:8] & {8{bram_wstb[1]}}: mem[32*ii + 15-:8]; mem[32*ii + 7-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[ 7-:8] & {8{bram_wstb[0]}}: mem[32*ii + 7-:8]; end end endgenerate // read from memory. Interface's protocol assumes returning data to delay reg [3:0] bram_raddr_r; reg [31:0] bram_rdata_r; always @ (posedge ACLK) begin bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r; bram_rdata_r <= bram_regen ? mem[32*bram_raddr_r + 31-:32] : bram_rdata_r; end assign bram_rdata = bram_rdata_r; // Interface's instantiation // Interface's instantiation axibram_write #( axibram_write #( .ADDRESS_BITS(16) .ADDRESS_BITS(16) Loading
dma_adapter.v +43 −41 Original line number Original line Diff line number Diff line Loading @@ -129,11 +129,12 @@ reg rd_reset_page; reg rd_next_page; reg rd_next_page; reg rd_data; reg rd_data; reg [6:0] rd_data_count; reg [6:0] rd_data_count; reg rd_en; wire rd_stop; wire rd_stop; wire rd_cnt_to_pull; wire rd_cnt_to_pull; assign rd_cnt_to_pull == 7'hf; assign rd_cnt_to_pull = 7'hf; assign rd_stop = rd_ack_in & rd_data_count == rd_cnt_to_pull; assign rd_stop = rd_ack_in & rd_data_count == rd_cnt_to_pull; assign rd_data_out = rd_data; assign rd_data_out = rd_data; Loading @@ -148,7 +149,7 @@ always @ (posedge clk) rd_en <= 1'b0; rd_en <= 1'b0; end end else else case (rst) case (rdwr_state) READ_IDLE: READ_IDLE: begin begin rdwr_state <= rd_start ? READ_WAIT_ADDR : READ_IDLE; rdwr_state <= rd_start ? READ_WAIT_ADDR : READ_IDLE; Loading @@ -159,7 +160,7 @@ always @ (posedge clk) end end READ_WAIT_ADDR: // wait until address information is sent to the bus and input buffer got data READ_WAIT_ADDR: // wait until address information is sent to the bus and input buffer got data begin begin rdwr_state <= membr_state == IDLE & rdata_done ? READ_DATA : READ_WAIT_ADDR; rdwr_state <= membr_state == READ_IDLE & rdata_done ? READ_DATA : READ_WAIT_ADDR; rd_done <= 1'b0; rd_done <= 1'b0; rd_data_count <= 7'h0; rd_data_count <= 7'h0; rd_next_page <= 1'b0; rd_next_page <= 1'b0; Loading @@ -181,6 +182,7 @@ always @ (posedge clk) rd_next_page <= 1'b0; rd_next_page <= 1'b0; rd_en <= 1'b0; rd_en <= 1'b0; end end endcase // Put data into buffer // Put data into buffer Loading Loading @@ -220,7 +222,7 @@ always @ (posedge clk) rdwr_state <= WRITE_IDLE; rdwr_state <= WRITE_IDLE; end end else else case (wr_state) case (rdwr_state) WRITE_IDLE: WRITE_IDLE: begin begin wr_data_count <= 7'd0; wr_data_count <= 7'd0; Loading @@ -234,26 +236,26 @@ always @ (posedge clk) end end WRITE_DATA: WRITE_DATA: begin begin wr_done <= wr_stop & membr_state == IDLE ? 1'b1 : 1'b0; wr_done <= wr_stop & membr_state == WRITE_IDLE ? 1'b1 : 1'b0; wr_data_count <= wr_val_in ? wr_data_count + 1'b1 : wr_data_count; wr_data_count <= wr_val_in ? wr_data_count + 1'b1 : wr_data_count; wr_data <= in_data : wr_data <= wr_data_in; wr_next_page <= wr_stop ? 1'b1 : 1'b0; wr_next_page <= wr_stop ? 1'b1 : 1'b0; wr_reset_page <= 1'b0; wr_reset_page <= 1'b0; wr_en <= wr_val_in; wr_en <= wr_val_in; wr_page_ready <= wr_stop ? 1'b1 : 1'b0; wr_page_ready <= wr_stop ? 1'b1 : 1'b0; rdwr_state <= wr_stop & membr_state == IDLE ? WRITE_IDLE : rdwr_state <= wr_stop & membr_state == WRITE_IDLE ? WRITE_IDLE : wr_stop ? WRITE_WAIT_ADDR : WRITE_DATA; wr_stop ? WRITE_WAIT_ADDR : WRITE_DATA; end end WRITE_WAIT_ADDR: // in case all data is written into a buffer, but address is still being issued on axi bus WRITE_WAIT_ADDR: // in case all data is written into a buffer, but address is still being issued on axi bus begin begin wr_done <= membr_state == IDLE ? 1'b1 : 1'b0; wr_done <= membr_state == WRITE_IDLE ? 1'b1 : 1'b0; wr_data_count <= 7'd0; wr_data_count <= 7'd0; wr_data <= 64'h0; wr_data <= 64'h0; wr_next_page <= 1'b0; wr_next_page <= 1'b0; wr_reset_page <= 1'b0; wr_reset_page <= 1'b0; wr_en <= 1'b0; wr_en <= 1'b0; wr_page_ready <= 1'b0; wr_page_ready <= 1'b0; rdwr_state <= membr_state == IDLE ? WRITE_IDLE : WRITE_WAIT_ADDR; rdwr_state <= membr_state == WRITE_IDLE ? WRITE_IDLE : WRITE_WAIT_ADDR; end end default: // read is executed default: // read is executed begin begin Loading Loading @@ -322,7 +324,7 @@ always @ (posedge clk) membr_start <= dma_start ? 1'b1 : 1'b0; membr_start <= dma_start ? 1'b1 : 1'b0; membr_setup <= dma_start ? 1'b1 : 1'b0; membr_setup <= dma_start ? 1'b1 : 1'b0; membr_done <= 1'b0; membr_done <= 1'b0; membr_state <= dma_start & membr_is_set ? MEMBR_LOADDDR : membr_state <= dma_start & membr_is_set ? MEMBR_LOADDR : dma_start ? MEMBR_MODE : MEMBR_IDLE; dma_start ? MEMBR_MODE : MEMBR_IDLE; end end MEMBR_MODE: MEMBR_MODE: Loading
dma_control.v +206 −43 Original line number Original line Diff line number Diff line Loading @@ -19,8 +19,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/> . * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ *******************************************************************************/ /* /* * Later on most of address evaluation logic could divided into 2 parts, which * Later on most of address evaluation logic could be divided into 2 parts, which * could be presented as 2 instances of 1 parameterized module * could be presented as 2 instances of 1 parameterized module * + split data and address parts. Didnt do that because not sure if * virtual channels would be implemented in the future */ */ module dma_control( module dma_control( input wire sclk, // sata clock input wire sclk, // sata clock Loading @@ -35,6 +37,19 @@ input wire dma_start, input wire dma_start, output wire dma_done, output wire dma_done, // adapter command iface input wire adp_busy, output wire [31:7] adp_addr, output wire adp_type, output wire adp_val, // sata host command iface input wire host_ready_for_cmd, output wire host_new_cmd, output wire [1:0] host_cmd_type, output wire [31:0] host_sector_count, output wire [31:0] host_sector_addr, // adapter data iface // adapter data iface // to main memory // to main memory output wire [63:0] to_data, output wire [63:0] to_data, Loading @@ -43,7 +58,7 @@ // from main memory // from main memory input wire [63:0] from_data, input wire [63:0] from_data, input wire from_val, input wire from_val, input wire from_ack output wire from_ack, // sata host iface // sata host iface // data from sata host // data from sata host Loading @@ -55,7 +70,156 @@ output wire out_val, output wire out_val, input wire out_busy input wire out_busy ); ); ////////////////////////////////////////////////////////////////////////////////////// //// ADDRESS ////////////////////////////////////////////////////////////////////////////////////// wire dma_done_adp; wire dma_done_host; assign dma_done = dma_done_host & dma_done_adp; reg adp_busy_sclk; /* * Commands to sata host fsm */ // for now only 2 states: idle and send a pulse reg host_issued; wire host_issued_set; wire host_issued_clr; assign dma_done_host = host_issued; assign host_issued_set = ~adp_busy_sclk & host_ready_for_cmd & dma_start; assign host_issued_clr = dma_done; always @ (posedge sclk) host_issued <= (host_issued | host_issued_set) & ~host_issued_clr & ~rst; // drive iface signals assign host_new_cmd = host_issued_set; assign host_cmd_type = dma_type; assign host_sector_count = sector_cnt; assign host_sector_addr = lba; /* * Commands to adapter fsm */ reg [33:0] quarter_sector_cnt; wire last_data; // last 128 bytes of data are transmitted now wire adp_val_sclk; reg [31:7] current_addr; reg current_type; // synchronize with host fsm reg adp_done; wire adp_done_clr; wire adp_done_set; assign dma_done_adp = adp_done; assign adp_done_set = state_wait_done & clr_wait_done & ~set_wait_busy; // = state_wait_done & set_idle; assign adp_done_clr = dma_done; always @ (posedge sclk) adp_done <= (adp_done | adp_done_set) & ~adp_done_clr & ~rst; // calculate sent sector count // 1 sector = 512 bytes for now => 1 quarter_sector = 128 bytes always @ (posedge sclk) quarter_sector_cnt <= ~set_wait_busy ? quarter_sector_cnt : state_idle ? 34'h0 : // new dma request quarter_sector_cnt + 1'b1; // same dma request, next 128 bytes // flags if we're currently sending the last data piece of dma transaction assign last_data = (sector_cnt == quarter_sector_cnt[33:2] + 1'b1) & (&quarter_sector_cnt[1:0]); // calculate outgoing address // increment every transaction to adapter always @ (posedge sclk) current_addr <= ~set_wait_busy ? current_addr : state_idle ? mem_address : // new dma request current_addr + 1'b1; // same dma request, next 128 bytes always @ (posedge sclk) current_type <= ~set_wait_busy ? current_type : state_idle ? dma_type : // new dma request current_type; // same dma request, next 128 bytes // fsm itself wire state_idle; reg state_wait_busy; reg state_wait_done; wire set_wait_busy; wire set_wait_done; wire clr_wait_busy; wire clr_wait_done; assign set_wait_busy = state_idle & host_issued_set // same start pulse for both fsms | state_wait_done & clr_wait_done & ~last_data; // still have some data to transmit within a current dma request assign set_wait_done = state_wait_busy & clr_wait_busy; assign clr_wait_busy = adp_busy_sclk; assign clr_wait_done = ~adp_busy_sclk; assign state_idle = ~state_wait_busy & ~state_wait_done; always @ (posedge sclk) begin state_wait_busy <= (state_wait_busy | set_wait_busy) & ~clr_wait_busy & ~rst; state_wait_done <= (state_wait_done | set_wait_done) & ~clr_wait_done & ~rst; end // conrol signals resync reg adp_val_r; reg adp_val_rr; always @ (posedge hclk) begin adp_val_r <= adp_val_sclk; adp_val_rr <= adp_val_r; end assign adp_addr = current_addr; assign adp_type = current_type; assign adp_val = adp_val_rr; // Maintaining correct adp_busy level @ sclk // assuming busy won't toggle rapidly, can afford not implementing handshakes wire adp_busy_sclk_set; wire adp_busy_sclk_clr; wire adp_busy_set; wire adp_busy_clr; reg adp_busy_r; assign adp_busy_set = adp_busy & ~adp_busy_r; assign adp_busy_clr = ~adp_busy & adp_busy_r; always @ (posedge sclk) adp_busy_sclk <= (adp_busy_sclk | adp_busy_sclk_set) & ~rst & ~adp_busy_sclk_clr; always @ (posedge hclk) adp_busy_r <= adp_busy; pulse_cross_clock adp_busy_set_pulse( .rst (rst), .src_clk (hclk), .dst_clk (sclk), .in_pulse (adp_busy_set), .out_pulse (adp_busy_sclk_set), .busy () ); pulse_cross_clock adp_busy_clr_pulse( .rst (rst), .src_clk (hclk), .dst_clk (sclk), .in_pulse (adp_busy_clr), .out_pulse (adp_busy_sclk_clr), .busy () ); ////////////////////////////////////////////////////////////////////////////////////// //// DATA ////////////////////////////////////////////////////////////////////////////////////// /* /* * from main memory resyncronisation circuit * from main memory resyncronisation circuit */ */ Loading @@ -65,8 +229,8 @@ reg [8:0] from_wr_addr; wire [8:0] from_wr_next_addr; wire [8:0] from_wr_next_addr; wire [9:0] from_rd_next_addr; wire [9:0] from_rd_next_addr; // gray coded addresses // gray coded addresses reg [9:0] from_rd_addr; reg [9:0] from_rd_addr_gr; reg [8:0] from_wr_addr; reg [8:0] from_wr_addr_gr; // anti-metastability shift registers for gray-coded addresses // anti-metastability shift registers for gray-coded addresses reg [9:0] from_rd_addr_gr_r; reg [9:0] from_rd_addr_gr_r; reg [8:0] from_wr_addr_gr_r; reg [8:0] from_wr_addr_gr_r; Loading Loading @@ -99,13 +263,13 @@ end always @ (posedge sclk) always @ (posedge sclk) begin begin from_wr_addr_gr_r <= rst ? 9'h0 : from_wr_addr; from_wr_addr_gr_r <= rst ? 9'h0 : from_wr_addr; from_wr_addr_gr_rr <= rst ? 9'h0 : from_wr_addr_rr; from_wr_addr_gr_rr <= rst ? 9'h0 : from_wr_addr_gr_r; end end // read address -> hclk (wr) domain to compare // read address -> hclk (wr) domain to compare always @ (posedge hclk) always @ (posedge hclk) begin begin from_rd_addr_gr_r <= rst ? 10'h0 : from_rd_addr; from_rd_addr_gr_r <= rst ? 10'h0 : from_rd_addr; from_rd_addr_gr_rr <= rst ? 10'h0 : from_rd_addr_rr; from_rd_addr_gr_rr <= rst ? 10'h0 : from_rd_addr_gr_r; end end // translate resynced write address into ordinary (non-gray) address // translate resynced write address into ordinary (non-gray) address genvar ii; genvar ii; Loading Loading @@ -169,8 +333,8 @@ reg [9:0] to_wr_addr; wire [9:0] to_wr_next_addr; wire [9:0] to_wr_next_addr; wire [8:0] to_rd_next_addr; wire [8:0] to_rd_next_addr; // gray coded addresses // gray coded addresses reg [8:0] to_rd_addr; reg [8:0] to_rd_addr_gr; reg [9:0] to_wr_addr; reg [9:0] to_wr_addr_gr; // anti-metastability shift registers for gray-coded addresses // anti-metastability shift registers for gray-coded addresses reg [8:0] to_rd_addr_gr_r; reg [8:0] to_rd_addr_gr_r; reg [9:0] to_wr_addr_gr_r; reg [9:0] to_wr_addr_gr_r; Loading Loading @@ -204,16 +368,15 @@ end always @ (posedge hclk) always @ (posedge hclk) begin begin to_wr_addr_gr_r <= rst ? 10'h0 : to_wr_addr; to_wr_addr_gr_r <= rst ? 10'h0 : to_wr_addr; to_wr_addr_gr_rr <= rst ? 10'h0 : to_wr_addr_rr; to_wr_addr_gr_rr <= rst ? 10'h0 : to_wr_addr_gr_r; end end // read address -> sclk (wr) domain to compare // read address -> sclk (wr) domain to compare always @ (posedge sclk) always @ (posedge sclk) begin begin to_rd_addr_gr_r <= rst ? 9'h0 : to_rd_addr; to_rd_addr_gr_r <= rst ? 9'h0 : to_rd_addr; to_rd_addr_gr_rr <= rst ? 9'h0 : to_rd_addr_rr; to_rd_addr_gr_rr <= rst ? 9'h0 : to_rd_addr_gr_r; end end // translate resynced write address into ordinary (non-gray) address // translate resynced write address into ordinary (non-gray) address genvar ii; generate generate for (ii = 0; ii < 10; ii = ii + 1) for (ii = 0; ii < 10; ii = ii + 1) begin: to_wr_antigray begin: to_wr_antigray Loading
dma_regs.v 0 → 100644 +152 −0 Original line number Original line Diff line number Diff line /******************************************************************************* * Module: dma_regs * Date: 2015-07-11 * Author: Alexey * Description: temporary registers, connected to axi bus * * Copyright (c) 2015 Elphel, Inc. * dma_regs.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * dma_regs.v file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ module dma_regs #( parameter REGISTERS_CNT = 20 ) ( input wire rst, input wire ACLK, input wire sclk, // registers iface output wire [31:7] mem_address, output wire [31:0] lba, output wire [31:0] sector_cnt, output wire dma_type, output wire dma_start, input wire dma_done, // axi buffer iface output wire [31:0] bram_rdata, input wire [31:0] bram_raddr, input wire [31:0] bram_waddr, input wire [31:0] bram_wdata, input wire [3:0] bram_wstb, input wire bram_wen, input wire bram_ren, input wire bram_regen ); //reg [32*REGISTERS_CNT - 1:0] mem; /* * Converntional MAXI interface from x393 project, uses fifos, writes to/reads from memory */ /* * Temporary mapping: * rw 0x00: dma address (will automatically align to 128-bytes boundary, i.e. [6:0] -> 0 * rw 0x04: lba * rw 0x08: sector count * rw 0x0c: dma type (any(0x0c) => write) * r1c 0x10: writes: dma start (any(0x10) => start) * reads: dma status of last issued transfer (0xffffffff => done) * ro 0x14: dma last issued dma_address */ reg [31:0] reg00; reg [31:0] reg04; reg [31:0] reg08; reg [31:0] reg0c; reg [31:0] reg10; reg [31:0] reg14; wire dma_done_aclk; wire dma_start_aclk; reg dma_issued; wire [31:0] wdata; pulse_cross_clock dma_done_pulse( .rst (rst), .src_clk (sclk), .dst_clk (ACLK), .in_pulse (dma_done), .out_pulse (dma_done_aclk), .busy () ); pulse_cross_clock dma_start_pulse( .rst (rst), .src_clk (ACLK), .dst_clk (sclk), .in_pulse (dma_start_aclk & ~dma_issued), .out_pulse (dma_start), .busy () ); assign dma_start_aclk = bram_wen & (bram_waddr[3:0] == 4'h4) & |wdata; assign wdata = bram_wdata[31:0] & {{8{bram_wstb[3]}}, {8{bram_wstb[2]}}, {8{bram_wstb[1]}}, {8{bram_wstb[0]}}}; always @ (posedge ACLK) dma_issued <= (dma_issued | dma_start_aclk) & ~rst & ~dma_done_aclk; assign mem_address = reg00[31:7]; assign lba = reg04; assign sector_cnt = reg08; assign dma_type = |reg0c; always @ (posedge ACLK) begin reg00 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h0) ? wdata : reg00; reg04 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h1) ? wdata : reg04; reg08 <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h2) ? wdata : reg08; reg0c <= rst ? 32'h0 : bram_wen & (bram_waddr[3:0] == 4'h3) ? wdata : reg0c; reg10 <= rst ? 32'h0 : dma_start_aclk ? 32'h0 : dma_done_aclk ? 32'hffffffff : reg10; // status reg reg14 <= rst ? 32'h0 : dma_done_aclk ? reg00 : reg14; end // read from registers. Interface's protocol assumes returning data with a delay reg [3:0] bram_raddr_r; reg [31:0] bram_rdata_r; always @ (posedge ACLK) begin bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r; bram_rdata_r <= ~bram_regen ? bram_rdata_r : bram_raddr_r == 4'h0 ? reg00 : bram_raddr_r == 4'h1 ? reg04 : bram_raddr_r == 4'h2 ? reg08 : bram_raddr_r == 4'h3 ? reg0c : bram_raddr_r == 4'h4 ? reg10 : bram_raddr_r == 4'h5 ? reg14 : 32'hd34db33f; end assign bram_rdata = bram_rdata_r; /* // for testing purposes the 'memory' is a set of registers for now // later on will try to use them as an application level registers genvar ii; generate for (ii = 0; ii < REGISTERS_CNT; ii = ii + 1) begin: write_to_mem always @ (posedge ACLK) begin mem[32*ii + 31-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[31-:8] & {8{bram_wstb[3]}}: mem[32*ii + 31-:8]; mem[32*ii + 23-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[23-:8] & {8{bram_wstb[2]}}: mem[32*ii + 23-:8]; mem[32*ii + 15-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[15-:8] & {8{bram_wstb[1]}}: mem[32*ii + 15-:8]; mem[32*ii + 7-:8] <= bram_wen & (bram_waddr[3:0] == ii) ? bram_wdata[ 7-:8] & {8{bram_wstb[0]}}: mem[32*ii + 7-:8]; end end endgenerate // read from memory. Interface's protocol assumes returning data with a delay reg [3:0] bram_raddr_r; reg [31:0] bram_rdata_r; always @ (posedge ACLK) begin bram_raddr_r <= bram_ren ? bram_raddr[3:0] : bram_raddr_r; bram_rdata_r <= bram_regen ? mem[32*bram_raddr_r + 31-:32] : bram_rdata_r; end assign bram_rdata = bram_rdata_r; */ endmodule
sata_host.v +42 −4 Original line number Original line Diff line number Diff line Loading @@ -40,7 +40,7 @@ module sata_host( input wire data_clk_out, input wire data_clk_out, // timer // timer output wire sata_timer, output wire [31:0] sata_timer, // phy // phy input wire clkin_150, input wire clkin_150, Loading @@ -50,9 +50,47 @@ module sata_host( output wire txp_out, output wire txp_out, output wire txn_out, output wire txn_out, input wire rxp_in, input wire rxp_in, input wire rxn_in input wire rxn_in, ); output wire plllkdet, output wire dcmlocked );/* assign ready_for_cmd = 1'b0; assign sata_core_full = 1'b0; assign sata_dout = 32'b0; assign sata_core_empty = 1'b0; assign sata_timer = 1'b0; assign linkup = 1'b0; assign txp_out = 1'b0; assign txn_out = 1'b0; assign plllkdet = 1'b0; assign dcmlocked = 1'b0;*/ sata_core sata_core( .ready_for_cmd (ready_for_cmd), .new_cmd (new_cmd), .cmd_type (cmd_type), .sector_count (sector_count), .sector_addr (sector_addr), .sata_din (sata_din), .sata_din_we (sata_din_we), .sata_core_full (sata_core_full), .sata_dout (sata_dout), .sata_dout_re (sata_dout_re), .sata_core_empty (sata_core_empty), .SATA_USER_DATA_CLK_IN (data_clk_in), .SATA_USER_DATA_CLK_OUT (data_clk_out), .sata_timer (sata_timer), .CLKIN_150 (clkin_150), .reset (reset), .LINKUP (linkup), .TXP0_OUT (txp_out), .TXN0_OUT (txn_out), .RXP0_IN (rxp_in), .RXN0_IN (rxn_in), .PLLLKDET_OUT_N (plllkdet), .DCMLOCKED_OUT (dcmlocked) ); endmodule endmodule