diff --git a/doc/index.rst b/doc/index.rst index b05bc6a..34dbf15 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -105,6 +105,38 @@ serv_mem_if serv_mem_if prepares the data to be sent out on the dbus during store operations and serializes the incoming data during loads +The memory interface is centered around four byte-wide shift registers connected in series. During store operations, the `dat_en` signal is asserted long enough to shift in the data from rs2 to the right place in the shift registers and the parallel output of the shift registers is then presented to the data bus as a 32-bit word together with a byte mask. The `Data bus byte mask`_ table summarizes the logic for when the individual byte select signals are asserted depending on the two LSB of the data address together with the size (byte, halfword, word) of the write operation. + +During load operations, the data from the bus is latched into the shift registers. `dat_en` is again asserted to shift out data from the registers. `i_lsb` decides from which byte stage of the shift register to tap the data, depending on the alignment of the received data. The `dat_valid` signal makes sure to only present valid data to `o_rd` and otherwise fill in with zeros or sign extension. + +When SERV is built with `WITH_CSR`, there is also logic to detect misaligned accesses which asserts the o_misalign flag to the core. + +.. image:: serv_mem_if_int.png + +.. _`Data bus byte mask`: + ++-------+---+---------------------+-----------------+----------------------+-------------+ +|op type|lsb| 3| 2| 1| 0| ++=======+===+=====================+=================+======================+=============+ +|sb | 00| 0| 0| 0| 1| ++-------+---+---------------------+-----------------+----------------------+-------------+ +|sb | 01| 0| 0| 1| 0| ++-------+---+---------------------+-----------------+----------------------+-------------+ +|sb | 10| 0| 1| 0| 0| ++-------+---+---------------------+-----------------+----------------------+-------------+ +|sb | 11| 1| 0| 0| 0| ++-------+---+---------------------+-----------------+----------------------+-------------+ +|sh | 00| 0| 0| 1| 1| ++-------+---+---------------------+-----------------+----------------------+-------------+ +|sh | 10| 1| 1| 0| 0| ++-------+---+---------------------+-----------------+----------------------+-------------+ +|sw | 00| 1| 1| 1| 1| ++-------+---+---------------------+-----------------+----------------------+-------------+ +|Logic |`(i_lsb == 11) |` |`(i_lsb == 10 |)`|`(i_lsb == 01) |` |`i_lsb == 0` | +|expression |`i_word |` |`i_word` |`i_word |` | | +| |`(i_half & i_lsb[1])`| |`(i_half & !i_lsb[1])`| | ++-------+---+---------------------+-----------------+----------------------+-------------+ + serv_rf_if ^^^^^^^^^^ diff --git a/doc/serv_mem_if_int.png b/doc/serv_mem_if_int.png new file mode 100644 index 0000000..aaef432 Binary files /dev/null and b/doc/serv_mem_if_int.png differ diff --git a/rtl/serv_mem_if.v b/rtl/serv_mem_if.v index b9ea5cb..c33e241 100644 --- a/rtl/serv_mem_if.v +++ b/rtl/serv_mem_if.v @@ -3,16 +3,19 @@ module serv_mem_if #(parameter WITH_CSR = 1) ( input wire i_clk, + //State input wire i_en, + input wire [1:0] i_bytecnt, + input wire [1:0] i_lsb, + output wire o_misalign, + //Control input wire i_mem_op, input wire i_signed, input wire i_word, input wire i_half, - input wire [1:0] i_bytecnt, + //Data input wire i_rs2, output wire o_rd, - input wire [1:0] i_lsb, - output wire o_misalign, //External interface output wire [31:0] o_wb_dat, output wire [3:0] o_wb_sel, @@ -20,12 +23,11 @@ module serv_mem_if input wire i_wb_ack); reg signbit; + reg [31:0] dat; wire [2:0] tmp = {1'b0,i_bytecnt}+{1'b0,i_lsb}; - reg [31:0] dat; - - wire dat_en = i_en & !tmp[2]; + wire dat_en = i_en & !tmp[2]; wire dat_cur = ((i_lsb == 2'd3) & dat[24]) | @@ -33,7 +35,10 @@ module serv_mem_if ((i_lsb == 2'd1) & dat[8]) | ((i_lsb == 2'd0) & dat[0]); - wire dat_valid = i_word | (i_bytecnt == 2'b00) | (i_half & !i_bytecnt[1]); + wire dat_valid = + i_word | + (i_bytecnt == 2'b00) | + (i_half & !i_bytecnt[1]); assign o_rd = i_mem_op & (dat_valid ? dat_cur : signbit & i_signed); diff --git a/rtl/serv_top.v b/rtl/serv_top.v index 92076af..a204d65 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -403,17 +403,17 @@ module serv_top #(.WITH_CSR (WITH_CSR)) mem_if ( - .i_clk (clk), + .i_clk (clk), //State - .i_en (cnt_en), - .i_bytecnt (mem_bytecnt), + .i_en (cnt_en), + .i_bytecnt (mem_bytecnt), .i_lsb (lsb), .o_misalign (mem_misalign), //Control - .i_mem_op (mem_op), - .i_signed (mem_signed), - .i_word (mem_word), - .i_half (mem_half), + .i_mem_op (mem_op), + .i_signed (mem_signed), + .i_word (mem_word), + .i_half (mem_half), //Data .i_rs2 (rs2), .o_rd (mem_rd),