Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add multi-port register file

  • Loading branch information...
commit 156705acf16af51fd1aaece4f183a7caa4067f24 1 parent 5e87d3a
@atgreen authored
View
39 moxie/cores/LVT-regs/LVT_2w4r.v
@@ -0,0 +1,39 @@
+
+`include "parameters.v"
+
+module LVT_2w4r(
+ input wire clock,
+
+ input wire we0,
+ input wire we1,
+
+ input wire `MEM_ADDR write_addr_0,
+ input wire `MEM_ADDR write_addr_1,
+
+ input wire `MEM_ADDR read_addr_0,
+ output reg `LVT_ENTRY read_0,
+ input wire `MEM_ADDR read_addr_1,
+ output reg `LVT_ENTRY read_1,
+ input wire `MEM_ADDR read_addr_2,
+ output reg `LVT_ENTRY read_2,
+ input wire `MEM_ADDR read_addr_3,
+ output reg `LVT_ENTRY read_3
+
+);
+
+reg `LVT_ENTRY live_value_table `LVT;
+
+// No write conflict resolution, but this is where it would be added.
+always @(posedge clock) begin
+ live_value_table[write_addr_0] <= `BANK_0;
+ live_value_table[write_addr_1] <= `BANK_1;
+end
+
+always @(posedge clock) begin
+ read_0 <= live_value_table[read_addr_0];
+ read_1 <= live_value_table[read_addr_1];
+ read_2 <= live_value_table[read_addr_2];
+ read_3 <= live_value_table[read_addr_3];
+end
+
+endmodule
View
24 moxie/cores/LVT-regs/MEM_1w1r.v
@@ -0,0 +1,24 @@
+
+`include "parameters.v"
+
+module MEM_1w1r(
+ input wire clock,
+ input wire we,
+ input wire `MEM_ADDR write_addr,
+ input wire `WORD write_data,
+ input wire `MEM_ADDR read_addr,
+ output reg `WORD read_data
+);
+
+reg `WORD memory `MEM;
+
+always @(posedge clock) begin
+ if (we)
+ memory[write_addr] <= write_data;
+end
+
+always @(posedge clock) begin
+ read_data <= memory[read_addr];
+end
+
+endmodule
View
59 moxie/cores/LVT-regs/MEM_1w4r.v
@@ -0,0 +1,59 @@
+
+`include "parameters.v"
+
+module MEM_1w4r(
+ input wire clock,
+ input wire we,
+ input wire `MEM_ADDR write_addr,
+ input wire `WORD write_data,
+
+ input wire `MEM_ADDR read_addr_0,
+ output wire `WORD read_data_0,
+ input wire `MEM_ADDR read_addr_1,
+ output wire `WORD read_data_1,
+ input wire `MEM_ADDR read_addr_2,
+ output wire `WORD read_data_2,
+ input wire `MEM_ADDR read_addr_3,
+ output wire `WORD read_data_3
+
+);
+
+
+MEM_1w1r MEM_1w1r_0(
+ .clock(clock),
+ .we(we),
+ .write_addr(write_addr),
+ .write_data(write_data),
+ .read_addr(read_addr_0),
+ .read_data(read_data_0)
+);
+
+MEM_1w1r MEM_1w1r_1(
+ .clock(clock),
+ .we(we),
+ .write_addr(write_addr),
+ .write_data(write_data),
+ .read_addr(read_addr_1),
+ .read_data(read_data_1)
+);
+
+MEM_1w1r MEM_1w1r_2(
+ .clock(clock),
+ .we(we),
+ .write_addr(write_addr),
+ .write_data(write_data),
+ .read_addr(read_addr_2),
+ .read_data(read_data_2)
+);
+
+MEM_1w1r MEM_1w1r_3(
+ .clock(clock),
+ .we(we),
+ .write_addr(write_addr),
+ .write_data(write_data),
+ .read_addr(read_addr_3),
+ .read_data(read_data_3)
+);
+
+
+endmodule
View
132 moxie/cores/LVT-regs/MEM_2w4r.v
@@ -0,0 +1,132 @@
+
+`include "parameters.v"
+
+module MEM_2w4r(
+ input wire clock,
+
+ input wire we0,
+ input wire we1,
+
+ input wire `MEM_ADDR write_addr_0,
+ input wire `WORD write_data_0,
+ input wire `MEM_ADDR write_addr_1,
+ input wire `WORD write_data_1,
+
+ input wire `MEM_ADDR read_addr_0,
+ output wire `WORD read_data_0,
+ input wire `MEM_ADDR read_addr_1,
+ output wire `WORD read_data_1,
+ input wire `MEM_ADDR read_addr_2,
+ output wire `WORD read_data_2,
+ input wire `MEM_ADDR read_addr_3,
+ output wire `WORD read_data_3
+);
+
+
+
+wire `LVT_ENTRY read_0;
+wire `LVT_ENTRY read_1;
+wire `LVT_ENTRY read_2;
+wire `LVT_ENTRY read_3;
+
+LVT_2w4r LVT_2w4r(
+ .clock(clock),
+
+ .we0(we0),
+ .write_addr_0(write_addr_0),
+ .we1(we1),
+ .write_addr_1(write_addr_1),
+
+ .read_addr_0(read_addr_0),
+ .read_0(read_0),
+ .read_addr_1(read_addr_1),
+ .read_1(read_1),
+ .read_addr_2(read_addr_2),
+ .read_2(read_2),
+ .read_addr_3(read_addr_3),
+ .read_3(read_3)
+);
+
+
+
+wire `WORD read_data_0_0;
+wire `WORD read_data_1_0;
+wire `WORD read_data_2_0;
+wire `WORD read_data_3_0;
+
+MEM_1w4r MEM_0(
+ .clock(clock),
+ .we(we0),
+ .write_addr(write_addr_0),
+ .write_data(write_data_0),
+
+ .read_addr_0(read_addr_0),
+ .read_data_0(read_data_0_0),
+ .read_addr_1(read_addr_1),
+ .read_data_1(read_data_1_0),
+ .read_addr_2(read_addr_2),
+ .read_data_2(read_data_2_0),
+ .read_addr_3(read_addr_3),
+ .read_data_3(read_data_3_0)
+);
+
+wire `WORD read_data_0_1;
+wire `WORD read_data_1_1;
+wire `WORD read_data_2_1;
+wire `WORD read_data_3_1;
+
+MEM_1w4r MEM_1(
+ .clock(clock),
+ .we(we1),
+ .write_addr(write_addr_1),
+ .write_data(write_data_1),
+
+ .read_addr_0(read_addr_0),
+ .read_data_0(read_data_0_1),
+ .read_addr_1(read_addr_1),
+ .read_data_1(read_data_1_1),
+ .read_addr_2(read_addr_2),
+ .read_data_2(read_data_2_1),
+ .read_addr_3(read_addr_3),
+ .read_data_3(read_data_3_1)
+);
+
+
+
+MUX_WORD_2to1 read_data_MUX_0(
+ .selector(read_0),
+
+ .input_0(read_data_0_0),
+ .input_1(read_data_0_1),
+
+ .output_0(read_data_0)
+);
+
+MUX_WORD_2to1 read_data_MUX_1(
+ .selector(read_1),
+
+ .input_0(read_data_1_0),
+ .input_1(read_data_1_1),
+
+ .output_0(read_data_1)
+);
+
+MUX_WORD_2to1 read_data_MUX_2(
+ .selector(read_2),
+
+ .input_0(read_data_2_0),
+ .input_1(read_data_2_1),
+
+ .output_0(read_data_2)
+);
+
+MUX_WORD_2to1 read_data_MUX_3(
+ .selector(read_3),
+
+ .input_0(read_data_3_0),
+ .input_1(read_data_3_1),
+
+ .output_0(read_data_3)
+);
+
+endmodule
View
31 moxie/cores/LVT-regs/MUX_WORD_2to1.v
@@ -0,0 +1,31 @@
+
+`include "parameters.v"
+
+module MUX_WORD_2to1(
+input wire `LVT_ENTRY selector,
+
+input wire `WORD input_0,
+input wire `WORD input_1,
+
+output reg `WORD output_0
+);
+
+always @(*) begin
+ case(selector)
+
+ `BANK_0: begin
+ output_0 <= input_0;
+ end
+
+ `BANK_1: begin
+ output_0 <= input_1;
+ end
+
+ default: begin
+ output_0 <= input_0;
+ end
+
+ endcase
+end
+
+endmodule
View
57 moxie/cores/LVT-regs/README.txt
@@ -0,0 +1,57 @@
+Live Value Table Memory Example Code
+
+Copyright (c) 2010, Charles Eric LaForest, University of Toronto
+Permission is granted for any use, and attribution would be nice. :)
+Share and Enjoy!
+
+If you found this useful, I'd love to hear about it: laforest@eecg.utoronto.ca
+(gifts of hardware and books are also welcome ;)
+
+This is some example code I lifted from my experiments. I've cleaned it up and
+it should still work, but if not, it'll definitely give you the overall idea of
+the Live Value Table (LVT) technique.
+
+The details are covered in the conference paper: "Efficient Multi-Ported
+Memories for FPGAs", presented at the 18th annual ACM/SIGDA International
+Symposium on Field Programmable Gate Arrays. You can also find it here:
+http://www.eecg.toronto.edu/~laforest/
+
+This code implements a 256x32 memory with two write ports and four read ports.
+Everything is parametrized by using macros, except for the port configuration.
+Changing that will require altering the files and connections between
+components. It's a very regular pattern, so don't worry.
+
+Files:
+
+parameters.h
+This file codifies the design parameters (memory width, depth, LVT entries,
+memory bank names, etc...) into macros for legibility and portability. It must
+be included at the beginning of all other design files.
+
+MUX_WORD_2to1.v
+A word-wide 2-to-1 multiplexer used to steer the read ports.
+The selector input comes from the LVT.
+
+MEM_1w1r.v
+A synchronous memory with one write port and one read port.
+This will usually be an exact match to a Block RAM.
+You may have to constrain your synthesis to use the RAM type you want.
+
+MEM_1w4r.v
+Simply replicates four instances of the 1w1r modules using a common write port.
+
+LVT_2w4r.v
+The Live Value Table proper. It's simply a synchronous memory, implemented in
+the obvious way, with the same port configuration and the same depth as the
+overall multi-ported memory. The end result will map to LUTs instead of Block
+RAMs. Note the width of this memory: it is log2(# of write ports). If you want
+to implement some form of write contention management, this is where to do it.
+Note the memory bank numbers at the writes.
+
+MEM_2w4r.v
+
+This module ties everything together: it instantiates the LVT, the two 1w4r
+memory banks, and the multiplexers controlled by the LVT outputs, making
+everything appear as a single 2w4r memory. There's only wiring in here, so you
+should be able to trace out a block-level schematic easily.
+
View
29 moxie/cores/LVT-regs/parameters.v
@@ -0,0 +1,29 @@
+
+`define WORD_WIDTH 32
+`define WORD [`WORD_WIDTH-1:0]
+
+`define MEM_ADDR_WIDTH 4
+`define MEM_ADDR [`MEM_ADDR_WIDTH-1:0]
+
+`define MEM_DEPTH 16
+`define MEM [`MEM_DEPTH-1:0]
+
+// Table pointing to which bank holds live register value
+`define LVT_ENTRY_WIDTH 1
+`define LVT_ENTRY [`LVT_ENTRY_WIDTH-1:0]
+// One entry for each register
+`define LVT_DEPTH (1 << `MEM_ADDR_WIDTH)
+`define LVT [`LVT_DEPTH-1:0]
+
+
+`define BANK_0 `LVT_ENTRY_WIDTH'd0
+`define BANK_1 `LVT_ENTRY_WIDTH'd1
+
+`define HIGH 1'b1
+`define LOW 1'b0
+
+// Used for various write enables
+`define READ `LOW
+`define WRITE `HIGH
+
+
View
1  moxie/cores/moxie/cpu_execute.v
@@ -106,6 +106,7 @@ module cpu_execute (/*AUTOARG*/
$display ("EXECUTE STALL");
memory_read_enable_o <= 0;
memory_write_enable_o <= 0;
+ register_write_enable_o <= 0;
end
else begin
case (current_state)
View
1  moxie/cores/moxie/cpu_fetch.v
@@ -71,6 +71,7 @@ module cpu_fetch #(parameter BOOT_ADDRESS = 32'h00001000
// Inputs
.rst_i (rst_i | flush_ififo),
.clk_i (clk_i),
+ .stall_i (stall_i),
.PC_i (fetchPC),
.newPC_p_i (newPC_p),
.write_en_i (wren),
View
302 moxie/cores/moxie/cpu_ififo.v
@@ -22,7 +22,8 @@ module cpu_ififo #(parameter BOOT_ADDRESS = 32'h00001000
// Outputs
PC_o, opcode_o, operand_o, valid_o, empty_o, full_o,
// Inputs
- rst_i, clk_i, write_en_i, read_en_i, data_i, newPC_p_i, PC_i
+ rst_i, clk_i, write_en_i, read_en_i, stall_i, data_i, newPC_p_i,
+ PC_i
);
// --- Clock and Reset ------------------------------------------
@@ -31,6 +32,8 @@ module cpu_ififo #(parameter BOOT_ADDRESS = 32'h00001000
input write_en_i ; // assert high to write data
input read_en_i ; // assert high to read data
+ input stall_i;
+
input [31:0] data_i ; // data to write
input [0:0] newPC_p_i;
@@ -118,155 +121,158 @@ module cpu_ififo #(parameter BOOT_ADDRESS = 32'h00001000
full_o <= 0;
valid_o <= 0;
end else begin
- PC_o <= (newPC_p_i ? PC_i : PC);
- // $display ("A %x buffer[read_ptr] = 0x%x", read_ptr, buffer[read_ptr][15:8]);
- // $display ("A BUFFER = 0x%x%x%x%x", buffer[0], buffer[1], buffer[2], buffer[3]);
- // $display ("A buffer_empty = %x", buffer_empty);
- // $display ("A ptr_gap = 0x%x", ptr_gap);
- // $display ("A 0x%x", !is_long_insn(buffer[read_ptr][15:8]));
- // $display ("A 0x%x", buffer[read_ptr][15:8]);
- if (buffer_empty ? !is_long_insn(data_i[31:24]) : !is_long_insn(buffer[read_ptr][15:8])) begin
- // This is a 16-bit instruction (either from input or from buffer).
- // $display ("B");
- if (write_en_i && (!read_en_i) && (can_write_32)) begin
- // $display ("Z");
- buffer[write_ptr] <= data_i[31:16];
- buffer[(write_ptr+1)%4] <= data_i[15:0];
- write_ptr <= (write_ptr + 2) % 4;
- valid_o <= 0;
- ptr_gap = ptr_gap + 2;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else if ((!write_en_i) && read_en_i && (can_read_16)) begin
- // $display ("Y");
- opcode_o <= buffer[read_ptr];
- valid_o <= 1;
- next_PC <= PC + 2;
- read_ptr <= (read_ptr + 1) % 4;
- ptr_gap = ptr_gap - 1;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else if (write_en_i && read_en_i && buffer_empty) begin
- // $display ("X");
- opcode_o <= data_i[31:16];
- buffer[0] <= data_i[15:0];
- write_ptr <= 1;
- read_ptr <= 0;
- ptr_gap = 1;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- valid_o <= 1;
- next_PC <= PC + 2;
- end
- else if (write_en_i && read_en_i && buffer_full) begin
- // $display ("W- ERROR");
- opcode_o <= buffer[read_ptr];
- valid_o <= 1;
- next_PC <= PC + 2;
- read_ptr <= (read_ptr + 1) % 4;
- ptr_gap = ptr_gap - 1;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else if (write_en_i && read_en_i && (can_write_32) && (can_read_16)) begin
- buffer[write_ptr] <= data_i[31:16];
- buffer[(write_ptr+1)%4] <= data_i[15:0];
- write_ptr <= (write_ptr + 2) % 4;
- opcode_o <= buffer[read_ptr];
- read_ptr <= (read_ptr + 1) % 4;
- valid_o <= 1;
- next_PC <= PC + 2;
- ptr_gap = ptr_gap + 1;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else begin
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- // #1 $display ("U - ERROR %x %x %x %x %x %x", write_en_i, read_en_i, write_ptr, read_ptr, ptr
- // _gap, full_o);
- end
+ if (stall_i == 1) begin
end else begin
- if (write_en_i && (!read_en_i) && (can_write_32)) begin
- buffer[write_ptr] <= data_i[31:16];
- buffer[write_ptr+1] <= data_i[15:0];
- write_ptr <= write_ptr + 2;
- ptr_gap = ptr_gap + 2;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else if ((!write_en_i) && read_en_i && (can_read_48)) begin
- opcode_o <= buffer[read_ptr];
- operand_o[31:16] <= buffer[read_ptr+1];
- operand_o[15:0] <= buffer[read_ptr+2];
- valid_o <= 1;
- next_PC <= PC + 6;
- read_ptr <= read_ptr + 3;
- ptr_gap = ptr_gap - 3;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else if (write_en_i && read_en_i && buffer_empty) begin
- buffer[write_ptr] <= data_i[31:16];
- buffer[write_ptr+1] <= data_i[15:0];
- write_ptr <= write_ptr + 2;
- valid_o <= 0;
- ptr_gap = ptr_gap + 2;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else if (write_en_i && read_en_i && buffer_full) begin
- opcode_o <= buffer[read_ptr];
- operand_o[31:16] <= buffer[read_ptr+1];
- operand_o[15:0] <= buffer[read_ptr+2];
- valid_o <= 1;
- next_PC <= PC + 6;
- read_ptr <= read_ptr + 3;
- ptr_gap = ptr_gap - 3;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else if (write_en_i && read_en_i && (can_write_32) && (can_read_48)) begin
- buffer[write_ptr] <= data_i[31:16];
- buffer[write_ptr+1] <= data_i[15:0];
- write_ptr <= write_ptr + 2;
- opcode_o <= buffer[read_ptr];
- operand_o[31:16] <= buffer[read_ptr+1];
- operand_o[15:0] <= buffer[read_ptr+2];
- read_ptr <= read_ptr + 3;
- valid_o <= 1;
- next_PC <= PC + 6;
- ptr_gap = ptr_gap - 1;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
- end
- else if (write_en_i && read_en_i && (ptr_gap == 2)) begin
- buffer[(write_ptr)%4] <= data_i[31:16];
- buffer[(write_ptr+1)%4] <= data_i[15:0];
- write_ptr <= (write_ptr + 2) % 4;
- opcode_o <= buffer[read_ptr];
- operand_o[31:16] <= buffer[(read_ptr+1)%4];
- operand_o[15:0] <= data_i[31:16];
- read_ptr <= (read_ptr + 3) % 4;
- valid_o <= 1;
- next_PC <= PC + 6;
- ptr_gap = 1;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ PC_o <= (newPC_p_i ? PC_i : PC);
+ // $display ("A %x buffer[read_ptr] = 0x%x", read_ptr, buffer[read_ptr][15:8]);
+ // $display ("A BUFFER = 0x%x%x%x%x", buffer[0], buffer[1], buffer[2], buffer[3]);
+ // $display ("A buffer_empty = %x", buffer_empty);
+ // $display ("A ptr_gap = 0x%x", ptr_gap);
+ // $display ("A 0x%x", !is_long_insn(buffer[read_ptr][15:8]));
+ // $display ("A 0x%x", buffer[read_ptr][15:8]);
+ if (buffer_empty ? !is_long_insn(data_i[31:24]) : !is_long_insn(buffer[read_ptr][15:8])) begin
+ // This is a 16-bit instruction (either from input or from buffer).
+ // $display ("B");
+ if (write_en_i && (!read_en_i) && (can_write_32)) begin
+ // $display ("Z");
+ buffer[write_ptr] <= data_i[31:16];
+ buffer[(write_ptr+1)%4] <= data_i[15:0];
+ write_ptr <= (write_ptr + 2) % 4;
+ valid_o <= 0;
+ ptr_gap = ptr_gap + 2;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if ((!write_en_i) && read_en_i && (can_read_16)) begin
+ // $display ("Y");
+ opcode_o <= buffer[read_ptr];
+ valid_o <= 1;
+ next_PC <= PC + 2;
+ read_ptr <= (read_ptr + 1) % 4;
+ ptr_gap = ptr_gap - 1;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if (write_en_i && read_en_i && buffer_empty) begin
+ // $display ("X");
+ opcode_o <= data_i[31:16];
+ buffer[0] <= data_i[15:0];
+ write_ptr <= 1;
+ read_ptr <= 0;
+ ptr_gap = 1;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ valid_o <= 1;
+ next_PC <= PC + 2;
+ end
+ else if (write_en_i && read_en_i && buffer_full) begin
+ // $display ("W- ERROR");
+ opcode_o <= buffer[read_ptr];
+ valid_o <= 1;
+ next_PC <= PC + 2;
+ read_ptr <= (read_ptr + 1) % 4;
+ ptr_gap = ptr_gap - 1;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if (write_en_i && read_en_i && (can_write_32) && (can_read_16)) begin
+ buffer[write_ptr] <= data_i[31:16];
+ buffer[(write_ptr+1)%4] <= data_i[15:0];
+ write_ptr <= (write_ptr + 2) % 4;
+ opcode_o <= buffer[read_ptr];
+ read_ptr <= (read_ptr + 1) % 4;
+ valid_o <= 1;
+ next_PC <= PC + 2;
+ ptr_gap = ptr_gap + 1;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else begin
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ // #1 $display ("U - ERROR %x %x %x %x %x %x", write_en_i, read_en_i, write_ptr, read_ptr, ptr
+ // _gap, full_o);
+ end
+ end else begin
+ if (write_en_i && (!read_en_i) && (can_write_32)) begin
+ buffer[write_ptr] <= data_i[31:16];
+ buffer[write_ptr+1] <= data_i[15:0];
+ write_ptr <= write_ptr + 2;
+ ptr_gap = ptr_gap + 2;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if ((!write_en_i) && read_en_i && (can_read_48)) begin
+ opcode_o <= buffer[read_ptr];
+ operand_o[31:16] <= buffer[read_ptr+1];
+ operand_o[15:0] <= buffer[read_ptr+2];
+ valid_o <= 1;
+ next_PC <= PC + 6;
+ read_ptr <= read_ptr + 3;
+ ptr_gap = ptr_gap - 3;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if (write_en_i && read_en_i && buffer_empty) begin
+ buffer[write_ptr] <= data_i[31:16];
+ buffer[write_ptr+1] <= data_i[15:0];
+ write_ptr <= write_ptr + 2;
+ valid_o <= 0;
+ ptr_gap = ptr_gap + 2;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if (write_en_i && read_en_i && buffer_full) begin
+ opcode_o <= buffer[read_ptr];
+ operand_o[31:16] <= buffer[read_ptr+1];
+ operand_o[15:0] <= buffer[read_ptr+2];
+ valid_o <= 1;
+ next_PC <= PC + 6;
+ read_ptr <= read_ptr + 3;
+ ptr_gap = ptr_gap - 3;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if (write_en_i && read_en_i && (can_write_32) && (can_read_48)) begin
+ buffer[write_ptr] <= data_i[31:16];
+ buffer[write_ptr+1] <= data_i[15:0];
+ write_ptr <= write_ptr + 2;
+ opcode_o <= buffer[read_ptr];
+ operand_o[31:16] <= buffer[read_ptr+1];
+ operand_o[15:0] <= buffer[read_ptr+2];
+ read_ptr <= read_ptr + 3;
+ valid_o <= 1;
+ next_PC <= PC + 6;
+ ptr_gap = ptr_gap - 1;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if (write_en_i && read_en_i && (ptr_gap == 2)) begin
+ buffer[(write_ptr)%4] <= data_i[31:16];
+ buffer[(write_ptr+1)%4] <= data_i[15:0];
+ write_ptr <= (write_ptr + 2) % 4;
+ opcode_o <= buffer[read_ptr];
+ operand_o[31:16] <= buffer[(read_ptr+1)%4];
+ operand_o[15:0] <= data_i[31:16];
+ read_ptr <= (read_ptr + 3) % 4;
+ valid_o <= 1;
+ next_PC <= PC + 6;
+ ptr_gap = 1;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4));
+ end
+ else if (write_en_i && read_en_i && (ptr_gap == 1)) begin
+ opcode_o <= buffer[read_ptr];
+ operand_o[31:16] <= data_i[31:16];
+ operand_o[15:0] <= data_i[15:0];
+ read_ptr <= (read_ptr + 1) % 4; // FIXME: this is probably not needed
+ valid_o <= 1;
+ next_PC <= PC + 6;
+ ptr_gap = 0;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4)); // FIXME: neither is this
+ end
+ else if (write_en_i && read_en_i && (ptr_gap == 3)) begin
+ buffer[write_ptr] <= data_i[31:16];
+ buffer[write_ptr+1] <= data_i[15:0];
+ write_ptr <= write_ptr + 2;
+ opcode_o <= buffer[read_ptr];
+ operand_o[31:16] <= buffer[(read_ptr+1)%4];
+ operand_o[15:0] <= buffer[(read_ptr+2)%4];
+ read_ptr <= read_ptr + 3;
+ valid_o <= 1;
+ next_PC <= PC + 6;
+ ptr_gap = ptr_gap - 1;
+ full_o = ((ptr_gap == 3) || (ptr_gap == 4)); // FIXME: this is probably not needed
+ end
end
- else if (write_en_i && read_en_i && (ptr_gap == 1)) begin
- opcode_o <= buffer[read_ptr];
- operand_o[31:16] <= data_i[31:16];
- operand_o[15:0] <= data_i[15:0];
- read_ptr <= (read_ptr + 1) % 4; // FIXME: this is probably not needed
- valid_o <= 1;
- next_PC <= PC + 6;
- ptr_gap = 0;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4)); // FIXME: neither is this
- end
- else if (write_en_i && read_en_i && (ptr_gap == 3)) begin
- buffer[write_ptr] <= data_i[31:16];
- buffer[write_ptr+1] <= data_i[15:0];
- write_ptr <= write_ptr + 2;
- opcode_o <= buffer[read_ptr];
- operand_o[31:16] <= buffer[(read_ptr+1)%4];
- operand_o[15:0] <= buffer[(read_ptr+2)%4];
- read_ptr <= read_ptr + 3;
- valid_o <= 1;
- next_PC <= PC + 6;
- ptr_gap = ptr_gap - 1;
- full_o = ((ptr_gap == 3) || (ptr_gap == 4)); // FIXME: this is probably not needed
- end
// else #1 $display ("L ERROR ptr_gap = 0x%x", ptr_gap);
end
end
View
83 moxie/cores/moxie/cpu_registerfile.v
@@ -18,54 +18,47 @@
// 02110-1301, USA.
module cpu_registerfile (/*AUTOARG*/
- // Outputs
- value1_o, value2_o, sp_o, fp_o,
- // Inputs
- rst_i, clk_i, write_enable_i, reg_write_index_i, reg_read_index1_i,
- reg_read_index2_i, value_i
- );
+ // Outputs
+ value0_o, value1_o, sp_o, fp_o,
+ // Inputs
+ rst_i, clk_i, write_enable0_i, write_enable1_i, value0_i, value1_i,
+ reg_write_index0_i, reg_write_index1_i, reg_read_index0_i,
+ reg_read_index1_i
+ );
+ // synthesis translate_off
+ initial
+ begin
+ $dumpvars(1, mem_2w4r);
+ end
+ // synthesis translate_on
+
// --- Clock and Reset ------------------------------------------
input rst_i, clk_i;
-
- input [0:0] write_enable_i;
- input [3:0] reg_write_index_i;
- input [3:0] reg_read_index1_i;
- input [3:0] reg_read_index2_i;
- input [31:0] value_i;
- output [31:0] value1_o;
- output [31:0] value2_o;
-
- output [31:0] sp_o;
- output [31:0] fp_o;
-
- wire [31:0] value1_o = registers[reg_read_index1_i];
- wire [31:0] value2_o = registers[reg_read_index2_i];
-
- reg [31:0] registers[0:15];
- assign fp_o = registers[0];
- assign sp_o = registers[1];
-
- always @ (posedge rst_i or posedge clk_i) begin
- if (rst_i) begin
- registers[0] <= 32'b00000000000000000000000000000000;
- registers[1] <= 32'b00000000000000000000000000000000;
- registers[2] <= 32'b00000000000000000000000000000000;
- registers[3] <= 32'b00000000000000000000000000000000;
- registers[4] <= 32'b00000000000000000000000000000000;
- registers[5] <= 32'b00000000000000000000000000000000;
- registers[6] <= 32'b00000000000000000000000000000000;
- registers[7] <= 32'b00000000000000000000000000000000;
- registers[8] <= 32'b00000000000000000000000000000000;
- registers[9] <= 32'b00000000000000000000000000000000;
- registers[10] <= 32'b00000000000000000000000000000000;
- registers[11] <= 32'b00000000000000000000000000000000;
- registers[12] <= 32'b00000000000000000000000000000000;
- registers[13] <= 32'b00000000000000000000000000000000;
- end else
- if (write_enable_i)
- registers[reg_write_index_i] <= value_i;
- end
+ output [31:0] value0_o, value1_o;
+ output [31:0] sp_o;
+ output [31:0] fp_o;
+ input write_enable0_i, write_enable1_i;
+ input [31:0] value0_i, value1_i;
+ input [0:3] reg_write_index0_i, reg_write_index1_i;
+ input [0:3] reg_read_index0_i, reg_read_index1_i;
+
+ MEM_2w4r mem_2w4r (clk_i,
+ write_enable0_i,
+ 0,
+ reg_write_index0_i,
+ value0_i,
+ reg_write_index1_i,
+ value1_i,
+ reg_read_index0_i,
+ value0_o,
+ reg_read_index1_i,
+ value1_o,
+ 0,
+ fp_o,
+ 1,
+ sp_o);
+
endmodule // cpu_registerfile
View
29 moxie/cores/moxie/moxie.v
@@ -116,18 +116,20 @@ module moxie (/*AUTOARG*/
// synthesis translate_on
cpu_registerfile regs (// Outputs
- .value1_o (rx_reg_value1),
- .value2_o (rx_reg_value2),
+ .value0_o (rx_reg_value1),
+ .value1_o (rx_reg_value2),
// Inputs
.rst_i (rst_i),
.clk_i (clk_i),
- .write_enable_i (wr_register_write_enable),
- .reg_write_index_i (wr_register_write_index),
- .reg_read_index1_i (xr_reg_index1),
- .reg_read_index2_i (xr_reg_index2),
+ .write_enable0_i (wr_register_write_enable),
+ .write_enable1_i (0),
+ .reg_write_index0_i (wr_register_write_index),
+ .reg_read_index0_i (xr_reg_index1),
+ .reg_read_index1_i (xr_reg_index2),
.sp_o (rx_sp),
.fp_o (rx_fp),
- .value_i (wr_reg_result));
+ .value0_i (wr_reg_result),
+ .value1_i (0));
always @(posedge clk_i)
if (rst_i) begin
@@ -215,15 +217,8 @@ module moxie (/*AUTOARG*/
.register_we_o (wr_register_write_enable),
.reg_result_o (wr_reg_result));
- assign hazard_war = 0;
-
- // (dr_A_read_enable & (xr_register_write_enable & (dr_reg_index1 == xr_register_write_index))) | (dr_B_read_enable & (xr_register_write_enable & (dr_reg_index2 == xr_register_write_index)));
-
- always @ (posedge clk_i) begin
- if (!rst_i & hazard_war)
- begin
-
- end
- end
+ assign hazard_war = xw_register_write_enable
+ & ((xw_register_write_index == dx_reg_index1)
+ | (xw_register_write_index == dx_reg_index2));
endmodule // moxie
View
6 moxie/firmware/bootrom.s
@@ -1,6 +1,7 @@
.text
ldi.l $sp, 0x4000000+4096
- xor $r0, $r0 # Zero out $r0
+ ldi.l $r0, 0x55555555
+# xor $r0, $r0 # Zero out $r0
mov $r1, $r0
mov $r2, $r0
mov $r3, $r0
@@ -8,7 +9,8 @@
ldi.l $r5, fun+0x1000
nop
nop
- jsr $r5
+
+# jsr $r5
loop: push $sp, $r0
inc $r0, 0x1 # Increment $r0
inc $r1, 0x1
View
2  moxie/soc/muskoka/sim/Makefile
@@ -2,6 +2,7 @@ MSOURCES = sim.v testram.v \
$(wildcard ../rtl/*.v) \
$(wildcard ../../../cores/moxie/*.v) \
$(wildcard ../../../cores/wishbone/*.v) \
+ $(wildcard ../../../cores/LVT-regs/*.v) \
$(wildcard ../../../cores/uart16550/rtl/verilog/*.v)
PROJECT = muskoka
@@ -14,6 +15,7 @@ bootrom.vh: ../../../firmware/bootrom.s
a.out: $(MSOURCES) bootrom.vh
iverilog -I../../../cores/moxie \
+ -I../../../cores/LVT-regs \
-I../../../cores/uart16550/rtl/verilog $(MSOURCES)
clean:
Please sign in to comment.
Something went wrong with that request. Please try again.