jsim3.v
`define OP 2:0 `define PC 11:4 `define RD 14:12 `define RA 18:16 `define RB 22:20 `define IM 35:24 `define OPHALT 3 `define OPSW 40 `define OPLW 41 `define OPBNE 42 `define OPJALR 43 module jsim3 #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=5) ( input clk, reset_n, output [(ADDR_WIDTH-1):0] addr, output [2:0] ra, rb, rd, output [(DATA_WIDTH-1):0] q, qi, qa, qb, qd, output [47:0] IF, output reg [47:0] ID, output reg [(DATA_WIDTH-1):0] ncycles ); reg we; single_port_ram dev1( .data(qb), .addr(addr), .we(we), .clk(clk), .q(q) ); regfile dev2( .clk(clk), .we(state==IFE), .ra(ra), .qa(qa), .rb(rb), .qb(qb), .rd(rd), .qd(qd) ); reg [4:0] pc; //wire [(DATA_WIDTH-1):0] q; wire [2:0] opcode; // Instruction Fetch (IF) reg [15:0] inst; reg active; wire ma2 = (ID[`OPSW] || ID[`OPLW]); //wire [15:0] qi; assign qi = (active? (ma2? inst: q): 16'h0000); assign opcode = qi[15:13]; // opcodes `include "opcodes.txt" wire op_add = opcode==ADD; wire op_nand = opcode==NAND; wire op_sw = opcode==SW; wire op_lw = opcode==LW; wire op_bne = opcode==BNE; wire op_jalr = opcode==JALR; wire flag1 = op_sw||op_bne; // no write-back wire flag2 = op_add||op_nand; // RRR format wire [2:0] rd1 = flag1? 3'h0: qi[12:10]; assign ra = qi[9:7]; assign rb = flag2? qi[2:0]: (flag1? qi[12:10]: 3'h0); assign IF[`OP] = opcode; assign IF[`OPHALT] = (qi==16'he071); // is halt assign IF[`PC] = pc; assign IF[`RD] = rd1; assign IF[`RA] = ra; assign IF[`RB] = rb; assign IF[`IM] = qi[9:0]; assign IF[`OPSW] = op_sw; assign IF[`OPLW] = op_lw; assign IF[`OPBNE] = op_bne; assign IF[`OPJALR] = op_jalr; wire memory_access = (IF[`OPSW] || IF[`OPLW]); //reg [(ADDR_WIDTH-1):0] jump; wire [(ADDR_WIDTH-1):0] jump = do_jump? qa[(ADDR_WIDTH-1):0]: (ID[`OPBNE]? d1[(ADDR_WIDTH-1):0]: 5'h00); wire do_branch = ID[`OPBNE] && (qa!=qb); wire do_jump = ID[`OPJALR]; wire [4:0] nextpc = pc + 1'b1; wire [4:0] newpc = (do_jump||do_branch? jump: nextpc); reg [4:0] maddr; assign addr = (state==MEM? d1: newpc ); wire [15:0] d1; wire [4:0] npc = ID[`PC] + 1'b1; assign rd = ID[`RD]; alu dev3( .a(qa), .b(qb), .pc({11'h000,npc}), .im10(ID[`IM]), .d(d1), .opcode(ID[`OP]) ); // writeback register multiplexer assign qd = (ID[`OPLW]? q: d1); reg [1:0] state; localparam RESET = 2'h0, IFE = 2'h1, MEM = 2'h2, HALT = 2'h3; wire [47:0] BLANK = 48'h0000_0000_0000; always @(posedge clk, negedge reset_n) begin if (!reset_n) begin active <= 1'b0; inst <= 16'h0000; pc <= 5'h1F; ID <= BLANK; state <= RESET; end else case (state) RESET: begin active <= 1'b0; state <= IFE; end IFE: begin active <= 1'b1; pc <= addr; if (do_jump) begin if (ID[`OPHALT]) state <= HALT; ID <= BLANK; end else if (do_branch) ID <= BLANK; else begin ID <= IF; if (memory_access) begin state <= MEM; we <= IF[`OPSW]; end end end MEM: begin state <= IFE; inst <= q; we <= 1'b0; end default: begin active <= 1'b0; state <= HALT; end endcase end always @(posedge clk or negedge reset_n) begin if (!reset_n) ncycles <= 16'h0000; else if (state==IFE || state==MEM) ncycles <= ncycles + 1'b1; end endmodule
alu.v
module alu( input [15:0] a, b, pc, input [9:0] im10, output reg [15:0] d, input [2:0] opcode ); `include "opcodes.txt" wire [15:0] seim = im10[6]? {9'h1FF,im10[6:0]}:{9'h000,im10[6:0]}; wire [15:0] sum = a + seim; always case (opcode) ADD: d <= a + b; ADDI: d <= sum; NAND: d <= ~(a&b); LUI: d <= {im10,6'h00}; SW: d <= sum; LW: d <= sum; BNE: d <= pc+seim; JALR: d <= pc; endcase endmodule
regfile.v
// The register file is a triple-port RAM // with two read addresses and a write address. // It is implemented with two double-port RAMs module regfile #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=3) ( input clk, input [(ADDR_WIDTH-1):0] ra, rb, rd, output [(DATA_WIDTH-1):0] qa, qb, input [(DATA_WIDTH-1):0] qd, input we ); double_port port1( .clk(clk), .we(we), .ra(ra), .rd(rd), .qa(qa), .qd(qd) ); double_port port2( .clk(clk), .we(we), .ra(rb), .rd(rd), .qa(qb), .qd(qd) ); endmodule module double_port #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=3) ( input [(DATA_WIDTH-1):0] qd, input [(ADDR_WIDTH-1):0] ra, rd, input we, clk, output [(DATA_WIDTH-1):0] qa ); // Declare the RAM variable reg [DATA_WIDTH-1:0] ram[0:2**ADDR_WIDTH-1]; // Initialize the RAM with $readmemb. Put the memory contents // in the data file. Without this file, // this design will not compile. // See Verilog LRM 1364-2001 Section 17.2.8 for details on the // format of this file. initial begin $readmemh("registers.txt", ram); end // Variable to hold the registered read address reg [ADDR_WIDTH-1:0] ra_reg; always @ (posedge clk) begin // Write if (we) ram[rd] <= qd; end always @ (posedge clk) ra_reg <= ra; // Continuous assignment implies read returns NEW data. // This is the natural behavior of the TriMatrix memory // blocks in Single Port mode. assign qa = (ra_reg? ram[ra_reg]:16'h0000); endmodule
single_port_ram.v
// Quartus II Verilog Template // Single port RAM with single read/write address module single_port_ram #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=5) ( input [(DATA_WIDTH-1):0] data, input [(ADDR_WIDTH-1):0] addr, input we, clk, output [(DATA_WIDTH-1):0] q ); // Declare the RAM variable reg [DATA_WIDTH-1:0] ram[0:2**ADDR_WIDTH-1]; // Initialize the RAM with $readmemb. Put the memory contents // in the file single_port_rom_init.txt. Without this file, // this design will not compile. // See Verilog LRM 1364-2001 Section 17.2.8 for details on the // format of this file. initial begin $readmemh("prog2.txt", ram); end // Variable to hold the registered read address reg [ADDR_WIDTH-1:0] addr_reg; always @ (posedge clk) begin // Write if (we) ram[addr] <= data; addr_reg <= addr; end // Continuous assignment implies read returns NEW data. // This is the natural behavior of the TriMatrix memory // blocks in Single Port mode. assign q = ram[addr_reg]; endmodule
fit.summary
Fitter Status : Successful - Wed Apr 14 21:46:07 2010 Quartus II Version : 9.0 Build 235 06/17/2009 SP 2 SJ Web Edition Revision Name : jsim3 Top-level Entity Name : jsim3 Family : Cyclone II Device : EP2C35F672C6 Timing Models : Final Total logic elements : 309 / 33,216 ( < 1 % ) Total combinational functions : 305 / 33,216 ( < 1 % ) Dedicated logic registers : 101 / 33,216 ( < 1 % ) Total registers : 101 Total pins : 208 / 475 ( 44 % ) Total virtual pins : 0 Total memory bits : 768 / 483,840 ( < 1 % ) Embedded Multiplier 9-bit elements : 0 / 70 ( 0 % ) Total PLLs : 0 / 4 ( 0 % )
tan.summary
-------------------------------------------------------------------------------------- Timing Analyzer Summary -------------------------------------------------------------------------------------- Type : Worst-case tsu Slack : N/A Required Time : None Actual Time : -0.082 ns From : reset_n To : we From Clock : -- To Clock : clk Failed Paths : 0 Type : Worst-case tco Slack : N/A Required Time : None Actual Time : 18.166 ns From : regfile:dev2|double_port:port2|altsyncram:ram_rtl_1|altsyncram_eui1:auto_generated|ram_block1a0~portb_address_reg2 To : qd[13] From Clock : clk To Clock : -- Failed Paths : 0 Type : Worst-case th Slack : N/A Required Time : None Actual Time : 0.312 ns From : reset_n To : we From Clock : -- To Clock : clk Failed Paths : 0 Type : Clock Setup: 'clk' Slack : N/A Required Time : None Actual Time : 95.10 MHz ( period = 10.515 ns ) From : regfile:dev2|double_port:port2|altsyncram:ram_rtl_1|altsyncram_eui1:auto_generated|ram_block1a0~portb_address_reg2 To : regfile:dev2|double_port:port2|altsyncram:ram_rtl_1|altsyncram_eui1:auto_generated|ram_block1a0~porta_datain_reg14 From Clock : clk To Clock : clk Failed Paths : 0 Type : Total number of failed paths Slack : Required Time : Actual Time : From : To : From Clock : To Clock : Failed Paths : 0 --------------------------------------------------------------------------------------
Maintained by John Loomis, last updated Thu Apr 15 14:50:46 2010