dsim2.v
module dsim2 #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=8) ( input clk, reset_n, recycle, output [(ADDR_WIDTH-1):0] addr, output we, output [2:0] rd, output [(DATA_WIDTH-1):0] q, qd, output reg [7:0] pc, output [(DATA_WIDTH-1):0] qi, output ma, rwe ); wire [2:0] ra, rb; wire [(DATA_WIDTH-1):0] qa, qb; single_port_ram dev1( .data(qa), .addr(addr[6:0]), .we(we), .clk(clk), .q(q) ); regfile dev2( .clk(clk), .ra(ra), .rb(rb), .rd(rd), .qa(qa), .qb(qb), .qd(qd), .we(rwe) ); //reg [7:0] pc; assign rwe = state==WB; wire [4:0] opcode; reg [15:0] inst; assign qi = (state==ID? q: inst); assign opcode = qi[15:11]; wire [7:0] immed = qi[7:0]; reg [2:0] state; localparam IF = 3'h0, ID = 3'h1, EX = 3'h2, MEM = 3'h3, WB = 3'h4, HALT = 3'h7; `include "opcodes.txt" wire op_sw = opcode==SW || opcode==SWI; wire op_lw = opcode==LW || opcode==LWI; wire op_lui = opcode==LUI; wire op_bne = opcode==BNE; wire op_jalr = opcode==JALR; assign we = (state==MEM) && op_sw; assign ma = (op_sw || op_lw); // memory_access assign rd = (op_sw||op_bne? 3'h0: qi[10:8]); assign ra = (op_lui||op_bne? qi[10:8]: qi[7:5]); assign rb = (op_sw? qi[10:8]: op_bne? qi[7:5]: qi[4:2]); wire do_branch = op_bne && (qa!=qb); reg [7:0] jump; wire [7:0] nextpc = pc + 1'b1; wire [7:0] newpc = (op_jalr||do_branch? jump: nextpc); assign addr = (state==MEM? qt[7:0]: newpc); // ALU wire [15:0] qt; alu dev3( .a(qa), .b(qb), .nextpc(nextpc), .imm8(immed), .d(qt), .opcode(opcode) ); // writeback register multiplexer assign qd = (op_lw? q: qt); always @(posedge clk, negedge reset_n) begin if (!reset_n) begin pc <= 8'hFF; state <= IF; end else case (state) IF: begin state <= ID; pc <= addr; end ID: begin // save results of IF phase inst <= q; state <= EX; end EX: begin jump <= op_jalr? qa[7:0]: qt[7:0]; if (inst == 16'h0000) state <= HALT; else if (ma) state <= MEM; else state <= WB; end MEM: begin state <= WB; end WB: begin state <= IF; end HALT: begin if (recycle) begin pc <= 8'hFF; state <= IF; end else state <= HALT; end default: state <= HALT; endcase end endmodule
alu.v
module alu( input [15:0] a, b, input [7:0] nextpc, input [7:0] imm8, output reg [15:0] d, input [4:0] opcode ); `include "opcodes.txt" wire [15:0] immse = imm8[7]? {8'hFF,imm8}:{8'h00,imm8}; wire [15:0] imm = {8'h00,imm8}; //wire [15:0] sum1 = a + immse; wire [15:0] seim = imm8[4]? {11'h7FF, imm8[4:0]} : {11'h000, imm8[4:0]}; wire [15:0] sum = a + seim; wire [1:0] opx = imm8[1:0]; reg [15:0] alu1, alu2; always case (opx) 0: alu1 <= a + b; 1: alu1 <= a - b; default: alu1 <= 16'h0; endcase always case (opx) 0: alu2 = a & b; 1: alu2 = a | b; 2: alu2 = a ^ b; 3: alu2 = ~(a|b); endcase always case (opcode) LWI: d <= imm; SWI: d <= imm; LI: d <= immse; LUI: d <= {imm8, a[7:0]}; LW: d <= sum; SW: d <= sum; ADDI: d <= sum; ALU1: d <= alu1; ALU2: d <= alu2; BNE: d <= {8'h00, nextpc+seim[7:0]}; JALR: d <= {8'h00, nextpc}; default: d <= 16'h0000; 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=7) ( 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("ram_init.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 06 22:21:59 2011 Quartus II Version : 9.0 Build 235 06/17/2009 SP 2 SJ Web Edition Revision Name : dsim2 Top-level Entity Name : dsim2 Family : Cyclone II Device : EP2C35F672C6 Timing Models : Final Total logic elements : 520 / 33,216 ( 2 % ) Total combinational functions : 504 / 33,216 ( 2 % ) Dedicated logic registers : 172 / 33,216 ( < 1 % ) Total registers : 172 Total pins : 73 / 475 ( 15 % ) Total virtual pins : 0 Total memory bits : 2,048 / 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 : 3.358 ns From : reset_n To : jump[5] From Clock : -- To Clock : clk Failed Paths : 0 Type : Worst-case tco Slack : N/A Required Time : None Actual Time : 17.486 ns From : single_port_ram:dev1|altsyncram:ram_rtl_0|altsyncram_rjb1:auto_generated|ram_block1a0~porta_address_reg6 To : qd[10] From Clock : clk To Clock : -- Failed Paths : 0 Type : Worst-case th Slack : N/A Required Time : None Actual Time : -0.292 ns From : reset_n To : inst[13] From Clock : -- To Clock : clk Failed Paths : 0 Type : Clock Setup: 'clk' Slack : N/A Required Time : None Actual Time : 87.84 MHz ( period = 11.384 ns ) From : single_port_ram:dev1|altsyncram:ram_rtl_0|altsyncram_rjb1:auto_generated|ram_block1a0~porta_address_reg6 To : regfile:dev2|double_port:port1|ram~75 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 Wed Apr 06 22:44:14 2011