mirror of https://github.com/YosysHQ/picorv32.git
Add PICORV32_REGS mechanism for ASIC sram instantiation
This commit is contained in:
parent
500db14e44
commit
ad08edd2e5
68
picorv32.v
68
picorv32.v
|
@ -42,6 +42,14 @@
|
||||||
`define assert(assert_expr) empty_statement
|
`define assert(assert_expr) empty_statement
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
// uncomment this for register file in extra module
|
||||||
|
// `define PICORV32_REGS picorv32_regs
|
||||||
|
|
||||||
|
// this macro can be used to check if the verilog files in your
|
||||||
|
// design are read in the correct order.
|
||||||
|
`define PICORV32_V
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
* picorv32
|
* picorv32
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
@ -149,7 +157,6 @@ module picorv32 #(
|
||||||
|
|
||||||
reg [63:0] count_cycle, count_instr;
|
reg [63:0] count_cycle, count_instr;
|
||||||
reg [31:0] reg_pc, reg_next_pc, reg_op1, reg_op2, reg_out;
|
reg [31:0] reg_pc, reg_next_pc, reg_op1, reg_op2, reg_out;
|
||||||
reg [31:0] cpuregs [0:regfile_size-1];
|
|
||||||
reg [4:0] reg_sh;
|
reg [4:0] reg_sh;
|
||||||
|
|
||||||
reg [31:0] next_insn_opcode;
|
reg [31:0] next_insn_opcode;
|
||||||
|
@ -175,6 +182,9 @@ module picorv32 #(
|
||||||
reg [31:0] irq_pending;
|
reg [31:0] irq_pending;
|
||||||
reg [31:0] timer;
|
reg [31:0] timer;
|
||||||
|
|
||||||
|
`ifndef PICORV32_REGS
|
||||||
|
reg [31:0] cpuregs [0:regfile_size-1];
|
||||||
|
|
||||||
integer i;
|
integer i;
|
||||||
initial begin
|
initial begin
|
||||||
if (REGS_INIT_ZERO) begin
|
if (REGS_INIT_ZERO) begin
|
||||||
|
@ -182,6 +192,7 @@ module picorv32 #(
|
||||||
cpuregs[i] = 0;
|
cpuregs[i] = 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
task empty_statement;
|
task empty_statement;
|
||||||
// This task is used by the `assert directive in non-formal mode to
|
// This task is used by the `assert directive in non-formal mode to
|
||||||
|
@ -1300,6 +1311,7 @@ module picorv32 #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
`ifndef PICORV32_REGS
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (resetn && cpuregs_write && latched_rd)
|
if (resetn && cpuregs_write && latched_rd)
|
||||||
cpuregs[latched_rd] <= cpuregs_wrdata;
|
cpuregs[latched_rd] <= cpuregs_wrdata;
|
||||||
|
@ -1325,6 +1337,37 @@ module picorv32 #(
|
||||||
cpuregs_rs2 = cpuregs_rs1;
|
cpuregs_rs2 = cpuregs_rs1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
`else
|
||||||
|
wire[31:0] cpuregs_rdata1;
|
||||||
|
wire[31:0] cpuregs_rdata2;
|
||||||
|
|
||||||
|
wire [5:0] cpuregs_waddr = latched_rd;
|
||||||
|
wire [5:0] cpuregs_raddr1 = ENABLE_REGS_DUALPORT ? decoded_rs1 : decoded_rs;
|
||||||
|
wire [5:0] cpuregs_raddr2 = ENABLE_REGS_DUALPORT ? decoded_rs2 : 0;
|
||||||
|
|
||||||
|
`PICORV32_REGS cpuregs (
|
||||||
|
.clk(clk),
|
||||||
|
.wen(resetn && cpuregs_write && latched_rd),
|
||||||
|
.waddr(cpuregs_waddr),
|
||||||
|
.raddr1(cpuregs_raddr1),
|
||||||
|
.raddr2(cpuregs_raddr2),
|
||||||
|
.wdata(cpuregs_wrdata),
|
||||||
|
.rdata1(cpuregs_rdata1),
|
||||||
|
.rdata2(cpuregs_rdata2)
|
||||||
|
);
|
||||||
|
|
||||||
|
always @* begin
|
||||||
|
decoded_rs = 'bx;
|
||||||
|
if (ENABLE_REGS_DUALPORT) begin
|
||||||
|
cpuregs_rs1 = decoded_rs1 ? cpuregs_rdata1 : 0;
|
||||||
|
cpuregs_rs2 = decoded_rs2 ? cpuregs_rdata2 : 0;
|
||||||
|
end else begin
|
||||||
|
decoded_rs = (cpu_state == cpu_state_ld_rs2) ? decoded_rs2 : decoded_rs1;
|
||||||
|
cpuregs_rs1 = decoded_rs ? cpuregs_rdata1 : 0;
|
||||||
|
cpuregs_rs2 = cpuregs_rs1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
assign launch_next_insn = cpu_state == cpu_state_fetch && decoder_trigger && (!ENABLE_IRQ || irq_delay || irq_active || !(irq_pending & ~irq_mask));
|
assign launch_next_insn = cpu_state == cpu_state_fetch && decoder_trigger && (!ENABLE_IRQ || irq_delay || irq_active || !(irq_pending & ~irq_mask));
|
||||||
|
|
||||||
|
@ -2051,6 +2094,29 @@ module picorv32 #(
|
||||||
`endif
|
`endif
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
// This is a simple example implementation of PICORV32_REGS.
|
||||||
|
// Use the PICORV32_REGS mechanism if you want to use custom
|
||||||
|
// memory resources to implement the processor register file.
|
||||||
|
// Note that your implementation must match the requirements of
|
||||||
|
// the PicoRV32 configuration. (e.g. QREGS, etc)
|
||||||
|
module picorv32_regs (
|
||||||
|
input clk, wen,
|
||||||
|
input [5:0] waddr,
|
||||||
|
input [5:0] raddr1,
|
||||||
|
input [5:0] raddr2,
|
||||||
|
input [31:0] wdata,
|
||||||
|
output [31:0] rdata1,
|
||||||
|
output [31:0] rdata2
|
||||||
|
);
|
||||||
|
reg [31:0] regs [0:30];
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
if (wen) regs[~waddr[4:0]] <= wdata;
|
||||||
|
|
||||||
|
assign rdata1 = regs[~raddr1[4:0]];
|
||||||
|
assign rdata2 = regs[~raddr2[4:0]];
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
* picorv32_pcpi_mul
|
* picorv32_pcpi_mul
|
||||||
|
|
|
@ -12,3 +12,4 @@
|
||||||
/hx8kdemo_syn_tb.vvp
|
/hx8kdemo_syn_tb.vvp
|
||||||
/hx8kdemo_tb.vvp
|
/hx8kdemo_tb.vvp
|
||||||
/testbench.vcd
|
/testbench.vcd
|
||||||
|
/cmos.log
|
||||||
|
|
|
@ -52,11 +52,16 @@ spiflash_tb: spiflash_tb.vvp firmware.hex
|
||||||
spiflash_tb.vvp: spiflash.v spiflash_tb.v
|
spiflash_tb.vvp: spiflash.v spiflash_tb.v
|
||||||
iverilog -s testbench -o $@ $^
|
iverilog -s testbench -o $@ $^
|
||||||
|
|
||||||
|
# ---- ASIC Synthesis Tests ----
|
||||||
|
|
||||||
|
cmos.log: spimemio.v simpleuart.v picosoc.v ../picorv32.v
|
||||||
|
yosys -l cmos.log -p 'synth -top picosoc; abc -g cmos2; opt -fast; stat' $^
|
||||||
|
|
||||||
# ---- Clean ----
|
# ---- Clean ----
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f testbench.vvp testbench.vcd spiflash_tb.vvp spiflash_tb.vcd
|
rm -f testbench.vvp testbench.vcd spiflash_tb.vvp spiflash_tb.vcd
|
||||||
rm -f firmware.elf firmware.hex firmware.bin
|
rm -f firmware.elf firmware.hex firmware.bin cmos.log
|
||||||
rm -f hx8kdemo.blif hx8kdemo.log hx8kdemo.asc hx8kdemo.rpt hx8kdemo.bin
|
rm -f hx8kdemo.blif hx8kdemo.log hx8kdemo.asc hx8kdemo.rpt hx8kdemo.bin
|
||||||
rm -f hx8kdemo_syn.v hx8kdemo_syn_tb.vvp hx8kdemo_tb.vvp
|
rm -f hx8kdemo_syn.v hx8kdemo_syn_tb.vvp hx8kdemo_tb.vvp
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
`ifdef PICORV32_V
|
||||||
|
`error "picosoc.v must be read before picorv32.v!"
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`define PICORV32_REGS picosoc_regs
|
||||||
|
|
||||||
module picosoc (
|
module picosoc (
|
||||||
input clk,
|
input clk,
|
||||||
input resetn,
|
input resetn,
|
||||||
|
@ -82,7 +88,7 @@ module picosoc (
|
||||||
wire [31:0] spimem_rdata;
|
wire [31:0] spimem_rdata;
|
||||||
|
|
||||||
reg ram_ready;
|
reg ram_ready;
|
||||||
reg [31:0] ram_rdata;
|
wire [31:0] ram_rdata;
|
||||||
|
|
||||||
assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01);
|
assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01);
|
||||||
assign iomem_wstrb = mem_wstrb;
|
assign iomem_wstrb = mem_wstrb;
|
||||||
|
@ -178,17 +184,56 @@ module picosoc (
|
||||||
.reg_dat_wait(simpleuart_reg_dat_wait)
|
.reg_dat_wait(simpleuart_reg_dat_wait)
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [31:0] memory [0:MEM_WORDS-1];
|
always @(posedge clk)
|
||||||
|
ram_ready <= mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS;
|
||||||
|
|
||||||
|
picosoc_mem #(.WORDS(MEM_WORDS)) memory (
|
||||||
|
.clk(clk),
|
||||||
|
.wen((mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) ? mem_wstrb : 4'b0),
|
||||||
|
.addr(mem_addr[23:2]),
|
||||||
|
.wdata(mem_wdata),
|
||||||
|
.rdata(ram_rdata)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// Implementation note:
|
||||||
|
// Replace the following two modules with wrappers for your SRAM cells.
|
||||||
|
|
||||||
|
module picosoc_regs (
|
||||||
|
input clk, wen,
|
||||||
|
input [5:0] waddr,
|
||||||
|
input [5:0] raddr1,
|
||||||
|
input [5:0] raddr2,
|
||||||
|
input [31:0] wdata,
|
||||||
|
output [31:0] rdata1,
|
||||||
|
output [31:0] rdata2
|
||||||
|
);
|
||||||
|
reg [31:0] regs [0:31];
|
||||||
|
|
||||||
|
always @(posedge clk)
|
||||||
|
if (wen) regs[waddr[4:0]] <= wdata;
|
||||||
|
|
||||||
|
assign rdata1 = regs[raddr1[4:0]];
|
||||||
|
assign rdata2 = regs[raddr2[4:0]];
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module picosoc_mem #(
|
||||||
|
parameter integer WORDS = 256
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input [3:0] wen,
|
||||||
|
input [21:0] addr,
|
||||||
|
input [31:0] wdata,
|
||||||
|
output reg [31:0] rdata
|
||||||
|
);
|
||||||
|
reg [31:0] mem [0:WORDS-1];
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
ram_ready <= 0;
|
rdata <= mem[addr];
|
||||||
if (mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) begin
|
if (wen[0]) mem[addr][ 7: 0] <= wdata[ 7: 0];
|
||||||
ram_ready <= 1;
|
if (wen[1]) mem[addr][15: 8] <= wdata[15: 8];
|
||||||
ram_rdata <= memory[mem_addr >> 2];
|
if (wen[2]) mem[addr][23:16] <= wdata[23:16];
|
||||||
if (mem_wstrb[0]) memory[mem_addr >> 2][ 7: 0] <= mem_wdata[ 7: 0];
|
if (wen[3]) mem[addr][31:24] <= wdata[31:24];
|
||||||
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];
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue