SystemVeriogでTD4をAltera DE0 Boardに

以前に読んだCPUの創り方という本に載っている4bitのCPU「TD4」をAlteraのFPGA Board DE0に移植してみました。無駄にmoduleの数を増やしています。こことかこことかを参考にしました。


TD4.h

`define OPCODE_WIDTH  4
`define DATA_WIDTH    4

TD4.v

`include "TD4.h"
module TD4(
	input CLK, RST,
	input [`DATA_WIDTH-1:0] SW,
	output [9:0] LEDG
);
   wire [`DATA_WIDTH-1:0] _OUT_, _IN_;
   wire CLK1Hz;
	
   CLKGEN u_clkgen(.*);
   TD4_CORE u_td4_core (.*, .CLK(CLK1Hz));
	
//	assign LEDG[4] = CLK1Hz;
   assign LEDG[3:0] = _OUT_;
   assign LEDG[9:`DATA_WIDTH] = {10-`DATA_WIDTH{1'b0}};
   assign _IN_ = SW;
endmodule

TD4_CORE.v

`include "TD4.h"
module TD4_CORE(
	input CLK, RST,
	input [`DATA_WIDTH-1:0] _IN_,
	output wire [`DATA_WIDTH-1:0] _OUT_
);
   wire LOAD0, LOAD1, LOAD2, LOAD3;
   wire [`DATA_WIDTH-1:0] ALU_IN, ALU_OUT;
   wire [`DATA_WIDTH-1:0] A, B, IM, PC;
   wire [`DATA_WIDTH+`OPCODE_WIDTH-1:0] INST;
   wire [`OPCODE_WIDTH-1:0] OP;
   wire C, Cnext;
	assign OP = INST[`DATA_WIDTH+`OPCODE_WIDTH-1:`DATA_WIDTH];
	assign IM = INST[`DATA_WIDTH-1:0];
	
   // ROM
   ROM rom(.*);
   // OpCode Decode
  OpDecode u_opdecode (.*);
   // ALU
   ALU u_alu (.*);
   // Register + Register Control
   RegRW u_regrw(.*);
endmodule

OpDecode.v

include "TD4.h"
module OpDecode(
	input [`OPCODE_WIDTH-1:0] OP,
	input [`DATA_WIDTH-1:0]   A, B, _IN_,
	input C,
	output wire LOAD0, LOAD1,LOAD2, LOAD3, 
	output wire [`DATA_WIDTH-1:0] ALU_IN
);
  // Opcode decode
   assign SELECT_A = OP[0] | OP[3];
   assign SELECT_B = OP[0];
   assign LOAD0 =  OP[2] |  OP[3];
   assign LOAD1 = ~OP[2] |  OP[3];
   assign LOAD2 =  OP[2] | ~OP[3];
   assign LOAD3 = ~OP[2] | ~OP[3] | (~OP[0] & C);
  // Data selector
   assign ALU_IN = (~SELECT_B & ~SELECT_A) ? A :
                   (~SELECT_B &  SELECT_A) ? B :
                   ( SELECT_B & ~SELECT_A) ? _IN_ :
                   `DATA_WIDTH'd0;
endmodule

ALU.v

`include "TD4.h"
module ALU(
	input [`DATA_WIDTH-1:0]  ALU_IN,
	input [`DATA_WIDTH-1:0]  IM,
	output wire [`DATA_WIDTH-1:0] ALU_OUT, 
	output wire Cnext
);
   // ALU
   assign {Cnext, ALU_OUT} = {1'b0,ALU_IN}+{1'b0,IM};
endmodule

RegRW.v

`include "TD4.h"
module RegRW (
	input CLK, RST,
	input LOAD0, LOAD1, LOAD2, LOAD3, 
	input [`DATA_WIDTH-1:0] ALU_OUT,
	input Cnext,
	output reg [`DATA_WIDTH-1:0] A, B, PC, _OUT_,
	output reg C
);
always @(posedge CLK, posedge RST) begin
   if (RST) begin
  	A  <= `DATA_WIDTH'd0;
	B  <= `DATA_WIDTH'd0;
	PC <= `DATA_WIDTH'd0;
	C  <= Cnext;
   end
   else begin
	  if (~LOAD0) A <= ALU_OUT;
     if (~LOAD1) B <= ALU_OUT;
	  if (~LOAD2) _OUT_ <= ALU_OUT;
     if (~LOAD3)  
	     PC <= ALU_OUT;
	  else
		  PC <= PC + `DATA_WIDTH'd1;
	  C  <= Cnext;
   end
end	
endmodule

ROM.v

`include "TD4.h"

module ROM (
	input [`DATA_WIDTH-1:0] PC,
	output [`DATA_WIDTH+`OPCODE_WIDTH-1:0] INST
);
   reg [`DATA_WIDTH+`OPCODE_WIDTH-1:0] _ROM_ [2**`DATA_WIDTH-1:0];
   assign INST = _ROM_[PC];
	 // Ramen timer
   initial begin
	   _ROM_[0] =  8'b10110111; // OUT 0111   # LED
      _ROM_[1] =  8'b00000001; // ADD A,0001
      _ROM_[2] =  8'b11100001; // JNC 0001   # loop 16 times
      _ROM_[3] =  8'b00000001; // ADD A,0001
      _ROM_[4] =  8'b11100011; // JNC 0011   # loop 16 times
      _ROM_[5] =  8'b10110110; // OUT 0110   # LED
      _ROM_[6] =  8'b00000001; // ADD A,0001
      _ROM_[7] =  8'b11100110; // JNC 0110   # loop 16 times
      _ROM_[8] =  8'b00000001; // ADD A,0001 
      _ROM_[9] =  8'b11101000; // JNC 1000   # loop 16 times
      _ROM_[10] = 8'b10110000; // OUT 0000   # LED
      _ROM_[11] = 8'b10110100; // OUT 0100   # LED
      _ROM_[12] = 8'b00000001; // AND 0001
      _ROM_[13] = 8'b11101010; // JNC 1010   # loop 16 times
      _ROM_[14] = 8'b10111000; // OUT 1000   # LED
      _ROM_[15] = 8'b11111111; // JMP 1111
   end
endmodule

CLKGEN.v

module CLKGEN (
	input CLK, RST, 
	output reg CLK1Hz
);
reg [25:0] cnt;
wire cnt_1Hz;
always @(posedge CLK, posedge RST) begin
	if (RST) begin
		cnt <= 26'd0;
		CLK1Hz <= 1'b0;
	end
 	else begin
	   cnt <= cnt_1Hz ? 26'd0 : cnt+26'd1;
		CLK1Hz <= cnt >= 26'd25_000_000;
	end
end
assign cnt_1Hz = (cnt==26'd49_999_999);
endmodule