2

i'm implementing an instance of single cycle MIPS processor. i want to implement store half-word and store byte

I've added a new input signal to my "Data memory" to control what to store like the code below.

// this was prof. Harris implementation in "digital design and computer 
// architecture book" implementation before i turn the "we" (Write Enable) signal into 2 bits  

module dmem(input logic clk, [1:0]we, //where we is an output of the control unit
            input logic [31:0] a, wd, 
            output logic [31:0] rd);

logic [31:0] RAM[63:0];

assign rd = RAM[a[31:2]]; // word aligned

always_ff @(posedge clk)
    case(we)
        2'b01: RAM[a[31:2]] <= wd; // sw 
        2'b10: RAM[a[31:0]][15:0] <= wd[15:0]; // sh
        2'b11: RAM[a[31:0]][7:0] <= wd[7:0]; // sb
        default:
        // do nothing
        ...

is this realistic if it's not what is the conventional way to implement it?

I'm studying it as a hobby, sorry if my question seems to be stupid

Greg
  • 18,111
  • 5
  • 46
  • 68
  • 1
    No, that does not work. To be honest, it is a big mess. You should not ask us *"if it is realistic or not"* The normal way to find out is to write a test-bench and test your code. Just one tip: For 32 bits data and byte write enable you normally have 4 enable lines. – Oldfart Oct 09 '19 at 16:45
  • Thank you so much, I didn't know that enable normally has 4 lines – Abdullah Khalid Oct 09 '19 at 22:46
  • where can i find the normal standards? because i don't know what to google exactly – Abdullah Khalid Oct 10 '19 at 00:42
  • 1
    It is not an official standard, but of you look up the most uses buses e.g. AXI you find they all have a byte-write-enable for each byte lane. – Oldfart Oct 10 '19 at 03:27

2 Answers2

3

Your RAM is using word addresses, no?  I say this b/c the elements are word sized.

Thus, we have to use a word address to index them, so you'll have to use a[31:2] for all store types, not just sw.

The store half (sh) then will go to RAM[a[31:2]] [15:0] if the a[1] is even/0, and [31:16] if a[1] is odd/1.  (Assuming little endian — swap these if big endian.)

The store byte will go to RAM[a[31:2]] [7:0] if a[1:0] is 2'b00, [15:8] if 2'b01, [23:16] if 2'b10, and [31:24] if 2'b11.


Alternatively, you can model RAM using bytes, and then the sb will be trivial, while the sh and sw will be more complex: sw will require updating 4 different location in RAM, since they are bytes in this scheme.

Erik Eidt
  • 23,049
  • 2
  • 29
  • 53
3

The main index for the RAM must always be the word address. I am assuming half-word write can upper and lower portions of the word, and byte write can assign to any byte within the word.

You can use the +: slice operator (See Indexing vectors and arrays with +:) to assign a portion of the word

always @(posedge clk) // NOTE: always_ff is SystemVerilog
  case(we)
    2'b01: RAM[a[31:2]] <= wd; // sw 
    2'b10: RAM[a[31:2]][ {a[1],4'b0000} +: 16] <= wd[15:0]; // sh
    2'b11: RAM[a[31:2]][ {a[1:0],3'b000} +: 8] <= wd[7:0]; // sb
    default:
    // do nothing
  endcase

With SystemVerilog, there is also the option of multi-dimensional packed arrays

//    [shw][sby][dat]    [sw  ]
logic [1:0][1:0][7:0] RAM[63:0];

assign rd = RAM[a[31:2]]; // word aligned

always_ff @(posedge clk)
  case(we)
    2'b01: RAM[a[31:2]] <= wd; // sw 
    2'b10: RAM[a[31:2]][a[1]] <= wd[15:0]; // sh
    2'b11: RAM[a[31:2]][a[1]][a[0]] <= wd[7:0]; // sb
    default:
    // do nothing
  endcase

I don't know how well most synthesizers will treat multi-dimensional packed arrays. Any synthesizer compatible with IEEE1364-2001 or latter will support +:, however I have seen mix results in how efficient the results are compared nested case statements. You will need to experiment.

Greg
  • 18,111
  • 5
  • 46
  • 68