From bbbcea2faa8db842ca92f1f25b1c3ff0400c5160 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 7 Jun 2015 12:11:20 +0200 Subject: [PATCH] Added look-ahead write interface --- dhrystone/testbench.v | 45 +++++++++++++++++-------------- picorv32.v | 32 ++++++++++------------ scripts/synth_vivado_soc.v | 54 +++++++++++++++++++++++--------------- 3 files changed, 73 insertions(+), 58 deletions(-) diff --git a/dhrystone/testbench.v b/dhrystone/testbench.v index bfa9fbc..9e0d329 100644 --- a/dhrystone/testbench.v +++ b/dhrystone/testbench.v @@ -19,22 +19,29 @@ module testbench; wire [31:0] mem_wdata; wire [3:0] mem_wstrb; reg [31:0] mem_rdata; + wire mem_la_read; + wire mem_la_write; wire [31:0] mem_la_addr; + wire [31:0] mem_la_wdata; + wire [3:0] mem_la_wstrb; picorv32 uut ( - .clk (clk ), - .resetn (resetn ), - .trap (trap ), - .mem_valid (mem_valid ), - .mem_instr (mem_instr ), - .mem_ready (mem_ready ), - .mem_addr (mem_addr ), - .mem_wdata (mem_wdata ), - .mem_wstrb (mem_wstrb ), - .mem_rdata (mem_rdata ), - .mem_la_read(mem_la_read), - .mem_la_addr(mem_la_addr) + .clk (clk ), + .resetn (resetn ), + .trap (trap ), + .mem_valid (mem_valid ), + .mem_instr (mem_instr ), + .mem_ready (mem_ready ), + .mem_addr (mem_addr ), + .mem_wdata (mem_wdata ), + .mem_wstrb (mem_wstrb ), + .mem_rdata (mem_rdata ), + .mem_la_read (mem_la_read ), + .mem_la_write(mem_la_write), + .mem_la_addr (mem_la_addr ), + .mem_la_wdata(mem_la_wdata), + .mem_la_wstrb(mem_la_wstrb) ); reg [31:0] memory [0:64*1024/4-1]; @@ -45,19 +52,19 @@ module testbench; always @(posedge clk) begin if (mem_la_read) mem_rdata <= memory[mem_la_addr >> 2]; - if (mem_valid) begin - case (mem_addr) + if (mem_la_write) begin + case (mem_la_addr) 32'h1000_0000: begin `ifndef TIMING - $write("%c", mem_wdata); + $write("%c", mem_la_wdata); $fflush(); `endif end default: begin - if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0]; - if (mem_wstrb[1]) memory[mem_addr >> 2][15: 8] <= mem_wdata[15: 8]; - if (mem_wstrb[2]) memory[mem_addr >> 2][23:16] <= mem_wdata[23:16]; - if (mem_wstrb[3]) memory[mem_addr >> 2][31:24] <= mem_wdata[31:24]; + if (mem_la_wstrb[0]) memory[mem_la_addr >> 2][ 7: 0] <= mem_la_wdata[ 7: 0]; + if (mem_la_wstrb[1]) memory[mem_la_addr >> 2][15: 8] <= mem_la_wdata[15: 8]; + if (mem_la_wstrb[2]) memory[mem_la_addr >> 2][23:16] <= mem_la_wdata[23:16]; + if (mem_la_wstrb[3]) memory[mem_la_addr >> 2][31:24] <= mem_la_wdata[31:24]; end endcase end diff --git a/picorv32.v b/picorv32.v index f84897a..f26f629 100644 --- a/picorv32.v +++ b/picorv32.v @@ -43,7 +43,10 @@ module picorv32 #( // look-ahead interface output mem_la_read, - output [31:0] mem_la_addr + output mem_la_write, + output [31:0] mem_la_addr, + output reg [31:0] mem_la_wdata, + output reg [ 3:0] mem_la_wstrb ); localparam integer regfile_size = ENABLE_REGS_16_31 ? 32 : 16; localparam integer regindex_bits = ENABLE_REGS_16_31 ? 5 : 4; @@ -69,22 +72,29 @@ module picorv32 #( wire mem_done = mem_ready && ((mem_state[0] && (mem_do_rinst || mem_do_rdata)) || mem_state == 2); + assign mem_la_write = resetn && !mem_state && mem_do_wdata; assign mem_la_read = resetn && !mem_state && (mem_do_rinst || mem_do_prefetch || mem_do_rdata); - assign mem_la_addr = mem_do_prefetch || mem_do_rinst ? next_pc : {reg_op1[31:2], 2'b00}; + assign mem_la_addr = (mem_do_prefetch || mem_do_rinst) ? next_pc : {reg_op1[31:2], 2'b00}; always @* begin (* full_case *) case (mem_wordsize) 0: begin + mem_la_wdata = reg_op2; + mem_la_wstrb = 4'b1111; mem_buffer = 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_buffer = mem_rdata[15: 0]; 1'b1: mem_buffer = 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_buffer = mem_rdata[ 7: 0]; 2'b01: mem_buffer = mem_rdata[15: 8]; @@ -102,6 +112,8 @@ module picorv32 #( end else case (mem_state) 0: begin mem_addr <= mem_la_addr; + mem_wdata <= mem_la_wdata; + mem_wstrb <= mem_la_wstrb; if (mem_do_prefetch || mem_do_rinst || mem_do_rdata) begin mem_valid <= 1; mem_instr <= mem_do_prefetch || mem_do_rinst; @@ -110,23 +122,7 @@ module picorv32 #( end if (mem_do_wdata) begin mem_valid <= 1; - mem_addr <= {reg_op1[31:2], 2'b00}; mem_instr <= 0; - (* full_case *) - case (mem_wordsize) - 0: begin - mem_wdata <= reg_op2; - mem_wstrb <= 4'b1111; - end - 1: begin - mem_wdata <= {2{reg_op2[15:0]}}; - mem_wstrb <= reg_op1[1] ? 4'b1100 : 4'b0011; - end - 2: begin - mem_wdata <= {4{reg_op2[7:0]}}; - mem_wstrb <= 4'b0001 << reg_op1[1:0]; - end - endcase mem_state <= 2; end end diff --git a/scripts/synth_vivado_soc.v b/scripts/synth_vivado_soc.v index b63c524..0b92d39 100644 --- a/scripts/synth_vivado_soc.v +++ b/scripts/synth_vivado_soc.v @@ -5,7 +5,7 @@ module test_soc ( input resetn, output trap, output [7:0] out_byte, - output out_byte_en, + output reg out_byte_en, output monitor_valid, output [31:0] monitor_addr, @@ -20,22 +20,29 @@ module test_soc ( wire [31:0] mem_wdata; wire [3:0] mem_wstrb; reg [31:0] mem_rdata; + wire mem_la_read; + wire mem_la_write; wire [31:0] mem_la_addr; + wire [31:0] mem_la_wdata; + wire [3:0] mem_la_wstrb; picorv32 uut ( - .clk (clk ), - .resetn (resetn ), - .trap (trap ), - .mem_valid(mem_valid), - .mem_instr(mem_instr), - .mem_ready(mem_ready), - .mem_addr (mem_addr ), - .mem_wdata(mem_wdata), - .mem_wstrb(mem_wstrb), - .mem_rdata(mem_rdata), - .mem_la_read(mem_la_read), - .mem_la_addr(mem_la_addr) + .clk (clk ), + .resetn (resetn ), + .trap (trap ), + .mem_valid (mem_valid ), + .mem_instr (mem_instr ), + .mem_ready (mem_ready ), + .mem_addr (mem_addr ), + .mem_wdata (mem_wdata ), + .mem_wstrb (mem_wstrb ), + .mem_rdata (mem_rdata ), + .mem_la_read (mem_la_read ), + .mem_la_write(mem_la_write), + .mem_la_addr (mem_la_addr ), + .mem_la_wdata(mem_la_wdata), + .mem_la_wstrb(mem_la_wstrb) ); assign monitor_valid = mem_valid; @@ -46,17 +53,22 @@ module test_soc ( initial $readmemh("../firmware/firmware.hex", memory); assign mem_ready = 1; - assign out_byte = mem_wdata[7:0]; - assign out_byte_en = mem_addr == 32'h1000_0000; always @(posedge clk) begin - mem_rdata <= memory[mem_la_addr >> 2]; - if (mem_valid && (mem_addr >> 2) < MEM_SIZE) begin - if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0]; - if (mem_wstrb[1]) memory[mem_addr >> 2][15: 8] <= mem_wdata[15: 8]; - if (mem_wstrb[2]) memory[mem_addr >> 2][23:16] <= mem_wdata[23:16]; - if (mem_wstrb[3]) memory[mem_addr >> 2][31:24] <= mem_wdata[31:24]; + out_byte_en <= 0; + if (mem_la_read) + mem_rdata <= memory[mem_la_addr >> 2]; + else + if (mem_la_write && (mem_la_addr >> 2) < MEM_SIZE) begin + if (mem_la_wstrb[0]) memory[mem_la_addr >> 2][ 7: 0] <= mem_la_wdata[ 7: 0]; + if (mem_la_wstrb[1]) memory[mem_la_addr >> 2][15: 8] <= mem_la_wdata[15: 8]; + if (mem_la_wstrb[2]) memory[mem_la_addr >> 2][23:16] <= mem_la_wdata[23:16]; + if (mem_la_wstrb[3]) memory[mem_la_addr >> 2][31:24] <= mem_la_wdata[31:24]; + end + else + if (mem_la_write && mem_la_addr == 32'h1000_0000) begin + out_byte_en <= 1; end end endmodule