mirror of https://github.com/YosysHQ/picorv32.git
Add big-endian support
Signed-off-by: Marcus Comstedt <marcus@mc.pp.se>
This commit is contained in:
parent
f9b1beb4cf
commit
b4777b378d
15
README.md
15
README.md
|
@ -320,6 +320,21 @@ uninitialized.) Note that the RISC-V calling convention requires the stack point
|
||||||
to be aligned on 16 bytes boundaries (4 bytes for the RV32I soft float calling
|
to be aligned on 16 bytes boundaries (4 bytes for the RV32I soft float calling
|
||||||
convention).
|
convention).
|
||||||
|
|
||||||
|
#### BIG_ENDIAN_OPERANDS (default 0)
|
||||||
|
|
||||||
|
Set this to 1 to enable big endian addressing for sub-word memory accesses,
|
||||||
|
i.e. the most significant bits at the lowest address.
|
||||||
|
|
||||||
|
#### BIG_ENDIAN_INSNS (default 0)
|
||||||
|
|
||||||
|
Set this to 1 to enable big endian instruction streams, i.e. the parcel in
|
||||||
|
`mem_rdata[31:16]` logically precedes the one in `mem_rdata[15:0]`,
|
||||||
|
and provides lower numbered bits in case the parcels are part of the same
|
||||||
|
instruction.
|
||||||
|
This is how the official RISC-V documents say instructions should be encoded
|
||||||
|
on big endian, but note that current toolchains do not support generating
|
||||||
|
code in this format.
|
||||||
|
|
||||||
|
|
||||||
Cycles per Instruction Performance
|
Cycles per Instruction Performance
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
110
picorv32.v
110
picorv32.v
|
@ -85,7 +85,9 @@ module picorv32 #(
|
||||||
parameter [31:0] LATCHED_IRQ = 32'h ffff_ffff,
|
parameter [31:0] LATCHED_IRQ = 32'h ffff_ffff,
|
||||||
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
|
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
|
||||||
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010,
|
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010,
|
||||||
parameter [31:0] STACKADDR = 32'h ffff_ffff
|
parameter [31:0] STACKADDR = 32'h ffff_ffff,
|
||||||
|
parameter [ 0:0] BIG_ENDIAN_OPERANDS = 0,
|
||||||
|
parameter [ 0:0] BIG_ENDIAN_INSNS = 0
|
||||||
) (
|
) (
|
||||||
input clk, resetn,
|
input clk, resetn,
|
||||||
output reg trap,
|
output reg trap,
|
||||||
|
@ -366,6 +368,7 @@ module picorv32 #(
|
||||||
reg clear_prefetched_high_word;
|
reg clear_prefetched_high_word;
|
||||||
reg [15:0] mem_16bit_buffer;
|
reg [15:0] mem_16bit_buffer;
|
||||||
|
|
||||||
|
wire [31:0] mem_rdata_insn;
|
||||||
wire [31:0] mem_rdata_latched_noshuffle;
|
wire [31:0] mem_rdata_latched_noshuffle;
|
||||||
wire [31:0] mem_rdata_latched;
|
wire [31:0] mem_rdata_latched;
|
||||||
|
|
||||||
|
@ -381,7 +384,13 @@ module picorv32 #(
|
||||||
(COMPRESSED_ISA && mem_xfer && (!last_mem_valid ? mem_la_firstword : mem_la_firstword_reg) && !mem_la_secondword && &mem_rdata_latched[1:0]));
|
(COMPRESSED_ISA && mem_xfer && (!last_mem_valid ? mem_la_firstword : mem_la_firstword_reg) && !mem_la_secondword && &mem_rdata_latched[1:0]));
|
||||||
assign mem_la_addr = (mem_do_prefetch || mem_do_rinst) ? {next_pc[31:2] + mem_la_firstword_xfer, 2'b00} : {reg_op1[31:2], 2'b00};
|
assign mem_la_addr = (mem_do_prefetch || mem_do_rinst) ? {next_pc[31:2] + mem_la_firstword_xfer, 2'b00} : {reg_op1[31:2], 2'b00};
|
||||||
|
|
||||||
assign mem_rdata_latched_noshuffle = (mem_xfer || LATCHED_MEM_RDATA) ? mem_rdata : mem_rdata_q;
|
generate if (BIG_ENDIAN_INSNS) begin
|
||||||
|
assign mem_rdata_insn = { mem_rdata[15:0], mem_rdata[31:16] };
|
||||||
|
end else begin
|
||||||
|
assign mem_rdata_insn = mem_rdata;
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
assign mem_rdata_latched_noshuffle = (mem_xfer || LATCHED_MEM_RDATA) ? mem_rdata_insn : mem_rdata_q;
|
||||||
|
|
||||||
assign mem_rdata_latched = COMPRESSED_ISA && mem_la_use_prefetched_high_word ? {16'bx, mem_16bit_buffer} :
|
assign mem_rdata_latched = COMPRESSED_ISA && mem_la_use_prefetched_high_word ? {16'bx, mem_16bit_buffer} :
|
||||||
COMPRESSED_ISA && mem_la_secondword ? {mem_rdata_latched_noshuffle[15:0], mem_16bit_buffer} :
|
COMPRESSED_ISA && mem_la_secondword ? {mem_rdata_latched_noshuffle[15:0], mem_16bit_buffer} :
|
||||||
|
@ -398,39 +407,70 @@ module picorv32 #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @* begin
|
generate if (BIG_ENDIAN_OPERANDS) begin
|
||||||
(* full_case *)
|
always @* begin
|
||||||
case (mem_wordsize)
|
(* full_case *)
|
||||||
0: begin
|
case (mem_wordsize)
|
||||||
mem_la_wdata = reg_op2;
|
0: begin
|
||||||
mem_la_wstrb = 4'b1111;
|
mem_la_wdata = reg_op2;
|
||||||
mem_rdata_word = mem_rdata;
|
mem_la_wstrb = 4'b1111;
|
||||||
end
|
mem_rdata_word = mem_rdata;
|
||||||
1: begin
|
end
|
||||||
mem_la_wdata = {2{reg_op2[15:0]}};
|
1: begin
|
||||||
mem_la_wstrb = reg_op1[1] ? 4'b1100 : 4'b0011;
|
mem_la_wdata = {2{reg_op2[15:0]}};
|
||||||
case (reg_op1[1])
|
mem_la_wstrb = reg_op1[1] ? 4'b0011 : 4'b1100;
|
||||||
1'b0: mem_rdata_word = {16'b0, mem_rdata[15: 0]};
|
case (reg_op1[1])
|
||||||
1'b1: mem_rdata_word = {16'b0, mem_rdata[31:16]};
|
1'b0: mem_rdata_word = {16'b0, mem_rdata[31:16]};
|
||||||
endcase
|
1'b1: mem_rdata_word = {16'b0, mem_rdata[15: 0]};
|
||||||
end
|
endcase
|
||||||
2: begin
|
end
|
||||||
mem_la_wdata = {4{reg_op2[7:0]}};
|
2: begin
|
||||||
mem_la_wstrb = 4'b0001 << reg_op1[1:0];
|
mem_la_wdata = {4{reg_op2[7:0]}};
|
||||||
case (reg_op1[1:0])
|
mem_la_wstrb = 4'b1000 >> reg_op1[1:0];
|
||||||
2'b00: mem_rdata_word = {24'b0, mem_rdata[ 7: 0]};
|
case (reg_op1[1:0])
|
||||||
2'b01: mem_rdata_word = {24'b0, mem_rdata[15: 8]};
|
2'b00: mem_rdata_word = {24'b0, mem_rdata[31:24]};
|
||||||
2'b10: mem_rdata_word = {24'b0, mem_rdata[23:16]};
|
2'b01: mem_rdata_word = {24'b0, mem_rdata[23:16]};
|
||||||
2'b11: mem_rdata_word = {24'b0, mem_rdata[31:24]};
|
2'b10: mem_rdata_word = {24'b0, mem_rdata[15: 8]};
|
||||||
endcase
|
2'b11: mem_rdata_word = {24'b0, mem_rdata[ 7: 0]};
|
||||||
end
|
endcase
|
||||||
endcase
|
end
|
||||||
end
|
endcase
|
||||||
|
end
|
||||||
|
end else begin // if (BIG_ENDIAN_OPERANDS)
|
||||||
|
always @* begin
|
||||||
|
(* full_case *)
|
||||||
|
case (mem_wordsize)
|
||||||
|
0: begin
|
||||||
|
mem_la_wdata = reg_op2;
|
||||||
|
mem_la_wstrb = 4'b1111;
|
||||||
|
mem_rdata_word = mem_rdata;
|
||||||
|
end
|
||||||
|
1: begin
|
||||||
|
mem_la_wdata = {2{reg_op2[15:0]}};
|
||||||
|
mem_la_wstrb = reg_op1[1] ? 4'b1100 : 4'b0011;
|
||||||
|
case (reg_op1[1])
|
||||||
|
1'b0: mem_rdata_word = {16'b0, mem_rdata[15: 0]};
|
||||||
|
1'b1: mem_rdata_word = {16'b0, mem_rdata[31:16]};
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
mem_la_wdata = {4{reg_op2[7:0]}};
|
||||||
|
mem_la_wstrb = 4'b0001 << reg_op1[1:0];
|
||||||
|
case (reg_op1[1:0])
|
||||||
|
2'b00: mem_rdata_word = {24'b0, mem_rdata[ 7: 0]};
|
||||||
|
2'b01: mem_rdata_word = {24'b0, mem_rdata[15: 8]};
|
||||||
|
2'b10: mem_rdata_word = {24'b0, mem_rdata[23:16]};
|
||||||
|
2'b11: mem_rdata_word = {24'b0, mem_rdata[31:24]};
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end endgenerate // else: !if(BIG_ENDIAN_OPERANDS)
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (mem_xfer) begin
|
if (mem_xfer) begin
|
||||||
mem_rdata_q <= COMPRESSED_ISA ? mem_rdata_latched : mem_rdata;
|
mem_rdata_q <= COMPRESSED_ISA ? mem_rdata_latched : mem_rdata_insn;
|
||||||
next_insn_opcode <= COMPRESSED_ISA ? mem_rdata_latched : mem_rdata;
|
next_insn_opcode <= COMPRESSED_ISA ? mem_rdata_latched : mem_rdata_insn;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (COMPRESSED_ISA && mem_done && (mem_do_prefetch || mem_do_rinst)) begin
|
if (COMPRESSED_ISA && mem_done && (mem_do_prefetch || mem_do_rinst)) begin
|
||||||
|
@ -602,13 +642,13 @@ module picorv32 #(
|
||||||
mem_valid <= 1;
|
mem_valid <= 1;
|
||||||
mem_la_secondword <= 1;
|
mem_la_secondword <= 1;
|
||||||
if (!mem_la_use_prefetched_high_word)
|
if (!mem_la_use_prefetched_high_word)
|
||||||
mem_16bit_buffer <= mem_rdata[31:16];
|
mem_16bit_buffer <= mem_rdata_insn[31:16];
|
||||||
end else begin
|
end else begin
|
||||||
mem_valid <= 0;
|
mem_valid <= 0;
|
||||||
mem_la_secondword <= 0;
|
mem_la_secondword <= 0;
|
||||||
if (COMPRESSED_ISA && !mem_do_rdata) begin
|
if (COMPRESSED_ISA && !mem_do_rdata) begin
|
||||||
if (~&mem_rdata[1:0] || mem_la_secondword) begin
|
if (~&mem_rdata_insn[1:0] || mem_la_secondword) begin
|
||||||
mem_16bit_buffer <= mem_rdata[31:16];
|
mem_16bit_buffer <= mem_rdata_insn[31:16];
|
||||||
prefetched_high_word <= 1;
|
prefetched_high_word <= 1;
|
||||||
end else begin
|
end else begin
|
||||||
prefetched_high_word <= 0;
|
prefetched_high_word <= 0;
|
||||||
|
|
Loading…
Reference in New Issue