I am implementing a MIPs like processor on a DE1 SoC for a University project. The processor is non-pipelined and its register file consists of 25 registers and has an asynchronous read thus Quartus synthesised it into ALM's as expected.
However, after implementing a generic 5 stage MIPs pipeline, the register file got synthesised into altsync_ram and thus is utilising the memory bits.
This is unexpected as the register file has an asynchronous read and thus Quartus shouldnt be able to be implements it as synchronous memory.
Any explanation or help would be appreciated.
So you're using an asynchronous chip select or read enable signal? Can you provide the code?
Are you saying you don't want the processor implemented using on-chip memory or is it not working correctly because it got synthesized into on-chip memory?
Im not using a read enable signal at all, the ALU is always reading the register file every clock cycle.
/*CPU register file*/ module registers #(parameter DATA_WIDTH=16) ( input logic clk, we, input logic [(DATA_WIDTH-1):0] wdata, input logic [4:0] rdest, input logic [4:0] rs1, input logic [4:0] rs2, output logic [(DATA_WIDTH-1):0] rdata1,rdata2 ); // Declare the RAM variable logic [DATA_WIDTH-1:0] gpr [0:24]; //initialise memory to 0 initial for(int i=0; i<25;i++) gpr[i] = '0; always@(posedge clk) begin // Write enable if (we) gpr[rdest] <= wdata; //synchronous write end //read process assign rdata1 = gpr[rs1]; assign rdata2 = gpr[rs2]; endmodule
The output rdata1 and rdata2 are fed into further registers (ID/EX) as shown below as the processor is pipelined.
I didn't want the registers to be implemented as on-chip memory.
Although im more curious to know why Quartus did rather than prevent it.
1) For a synthesized design, you shouldn't use an initial statement. It is not synthesizable. If you want to initialize the registers to all 0, rely on all the registers naturally initializing low or use a normal clocked process based on a reset signal.
2) The registers were implemented as memory because you created them as a 2D array and you are using synchronous writes. If you don't want to use a memory block, either use a Quartus assignment in the Assignment Editor to not implement gpr as a memory (I'm forgetting the assignment name right now but you can choose to implement as registers instead of memory) or don't use a 2D array to create the registers.
Thanks for the tips!
However, I am still confused about a certain aspects of this.
The code I showed you above stayed the same and was implemented in two different processors.
One was a pipelined processor and in that the register file was synthesised into altsync_ram and used memory bits.
The other processor was non-pipelined and the register file was synthesised into registers/ALMs and used no memory bits.
Im confused about how the same code can get synthesised differently just by being implemented in different top level designs.
I would have to see what the module is connected to in the upper-level design. The choice is all based on the registering (or not registering) the inputs and outputs of the memory.