Won_Hyunho
Published

Artix7 - 16bit CPU Design

Design the structure of a 16-bit CPU

IntermediateShowcase (no instructions)490
Artix7 - 16bit CPU Design

Things used in this project

Hardware components

Arty A7: Artix-7 FPGA Development Board
Digilent Arty A7: Artix-7 FPGA Development Board
×1

Software apps and online services

Vivado Design Suite
AMD Vivado Design Suite

Story

Read more

Schematics

CPU Diagram

Code

cpu_top.v

Verilog
module cpu_top (clk100M, push_sw, seg_drv, an_sel);
parameter	BW = 16;
input				clk100M, push_sw;
output	[7:0]		seg_drv;	// muxed signal
output	[3:0]		an_sel;

reg [6:0]			seg_k;
reg [6:0]			seg_h;
reg [6:0]			seg_t;
reg [6:0]			seg_o;

//wire				ta, tb, td;
wire				clk;
wire				start;
wire	[7:0]		pc;
wire	[8:0]		addr_out;
wire	[BW-1:0]	data_out;
wire	[BW-1:0]	data_in;
wire	[2:0]		dr, sa, sb;
wire	[4:0]		fs;
wire				rw, mb, mw, mm, md;
wire				vflg, cflg, nflg, zflg;
wire	[BW-1:0]	r0_out;

//
`ifdef sim
ila_0 ILA (
.clk(clk),
.probe0(push_sw),
.probe1(pc),
.probe2(addr_out),
.probe3(data_out),
.probe4(data_in),
.probe5(dr),
.probe6(sa),
.probe7(sb),
.probe8(fs),
.probe9(rw),
.probe10(mb),
.probe11(mw),
.probe12(mm),
.probe13(md),
.probe14(vflg),
.probe15(cflg),
.probe16(nflg),
.probe17(zflg),
.probe18(r0_out)
);


//up_control inst_up_control (.clk(clk), .start(s_start), .ta(ta), .sa(sa), .tb(tb), .sb(sb), .td(td), .dr(dr), 
up_control inst_up_control (.clk(clk), .start(push_sw), .sa(sa), .sb(sb), .dr(dr), 
							.fs(fs), .pc(pc), .rw(rw), .mw(mw), .mb(mb), .md(md), .mm(mm), .data_in(data_in), 
							.vflg(vflg), .cflg(cflg), .nflg(nflg), .zflg(zflg));

//datapath_unit inst_datapath_unit (.clk(clk), .start(s_start), .ta(ta), .sa(sa), .tb(tb), .sb(sb), .td(td), .dr(dr), 
datapath inst_datapath_unit (.clk(clk), .start(push_sw), .sa(sa), .sb(sb), .dr(dr), 
								  .fs(fs), .pc(pc), .rw(rw), .mb(mb), .md(md), .mm(mm), .data_in(data_in), 
								  .vflg(vflg), .cflg(cflg), .nflg(nflg), .zflg(zflg), 
								  .data_out(data_out), .addr_out(addr_out), .r0_reg(r0_out));
`else
ila_0 ILA (
.clk(clk),
.probe0(start),
.probe1(pc),
.probe2(addr_out),
.probe3(data_out),
.probe4(data_in),
.probe5(dr),
.probe6(sa),
.probe7(sb),
.probe8(fs),
.probe9(rw),
.probe10(mb),
.probe11(mw),
.probe12(mm),
.probe13(md),
.probe14(vflg),
.probe15(cflg),
.probe16(nflg),
.probe17(zflg),
.probe18(r0_out)
);


//up_control inst_up_control (.clk(clk), .start(s_start), .ta(ta), .sa(sa), .tb(tb), .sb(sb), .td(td), .dr(dr), 
up_control inst_up_control (.clk(clk), .start(start), .sa(sa), .sb(sb), .dr(dr), 
							.fs(fs), .pc(pc), .rw(rw), .mw(mw), .mb(mb), .md(md), .mm(mm), .data_in(data_in), 
							.vflg(vflg), .cflg(cflg), .nflg(nflg), .zflg(zflg));

//datapath_unit inst_datapath_unit (.clk(clk), .start(s_start), .ta(ta), .sa(sa), .tb(tb), .sb(sb), .td(td), .dr(dr), 
datapath inst_datapath_unit (.clk(clk), .start(start), .sa(sa), .sb(sb), .dr(dr), 
								  .fs(fs), .pc(pc), .rw(rw), .mb(mb), .md(md), .mm(mm), .data_in(data_in), 
								  .vflg(vflg), .cflg(cflg), .nflg(nflg), .zflg(zflg), 
								  .data_out(data_out), .addr_out(addr_out), .r0_reg(r0_out));
`endif

ram_16x512 inst_ram_512x16b (.addra(addr_out), .clka(clk), .ena(1'b1), .dina(data_out), .wea(mw), .douta(data_in));


misc_blk inst_misc_blk (push_sw, clk100M, r0_out, start, clk, seg_drv, an_sel);

endmodule

datapath.v

Verilog
module datapath
#(
   parameter BW = 16
)
(
  input                 clk,
  input                 start,
  input      [2:0]      sa,
  input      [2:0]      sb,
  input      [2:0]      dr,
  input      [4:0]      fs,  
  input			 [7:0]	  	pc,  
  input                 rw,         
  ///////mb,mm,md
  input                 mb,
  input                 md,
  input                 mm,
  
  input      [BW-1:0]   data_in,
  output     reg        vflg,
  output     reg        cflg,
  output     reg        nflg,
  output     reg        zflg,
  output     [BW-1:0]   data_out,
  output     [8:0]      addr_out,
  output     [BW-1:0]     r0_reg           
);

wire [BW-1:0] w_a, w_b, w_muxb, w_fun, w_muxd;
wire r_v_flag;
wire r_c_flag;
wire r_n_flag;
wire r_z_flag;

assign data_out = w_muxb;

always@(posedge clk or negedge start)
  if(!start) begin
    vflg<=0;
    cflg<=0;
    nflg<=0;
    zflg<=0;
  end else if(rw)begin
    vflg<=r_v_flag;
    cflg<=r_c_flag;
    nflg<=r_n_flag;
    zflg<=r_z_flag;
  end

//mux 2
mux_2t1 
#(
  .BW(BW)
)
mux_2t1_b
(
  .i_data_0(w_b),
  .i_data_1({13'b0,sb}),
  .sel(mb),
  .o_data(w_muxb)
);

mux_2t1 
#(
  .BW(9)
)
mux_2t1_m //9bit address
(
  .i_data_0(w_a[8:0]),
  .i_data_1({1'b0,pc}),//9bit
  .sel(mm),
  .o_data(addr_out)
);

mux_2t1 
#(
  .BW(BW)
)
mux_2t1_d //9bit address
(
  .i_data_0(w_fun), //16bit
  .i_data_1(data_in),//16bit
  .sel(md),
  .o_data(w_muxd)
);

register_file
register_file_u0
(
  .clk(clk),
  .reset_n(start),
  .i_data(w_muxd),
  .sa(sa),
  .sb(sb),
  .dr(dr),
  .en(rw),
  .o_a(w_a),
  .o_b(w_b),
  .reg_0(r0_reg)
);

function_unit
#(
  .BW(BW)
)
function_unit_u0
(
  .i_a(w_a),
  .i_b(w_muxb),
  .opcode(fs),
  .sa(sa),
  .v_flag(r_v_flag),
  .c_flag(r_c_flag),
  .n_flag(r_n_flag),
  .z_flag(r_z_flag),
  .o_fun(w_fun)
);
endmodule

shifter

Verilog
`timescale 1ns/1ps

module br_unit
#(
  parameter   BW = 16
)
(
  input      [BW-1:0]   i_b,
  input      [2:0]      sel,//S2,S1,S0
  input      [3:0]      i_num, //fs[0],SA
  output reg [BW-1:0]   o_b
);
localparam  NO_SHIFT  = 3'b000;
localparam  LE_SHIFT  = 3'b001;
localparam  RI_SHIFT  = 3'b010;
localparam  AR_SHIFT  = 3'b011;
localparam  LE_ROTATE = 3'b100;
localparam  RI_ROTATE = 3'b101;
localparam  BR_ROTATE = 3'b110;
localparam  BL_ROTATE = 3'b111;

reg         [3:0]      r_num;
reg         [2*BW-2:0] r_b;
wire        [BW-1:0]   w_b_right;
wire        [BW-1:0]   w_b_left;

always@(*) begin
   case(sel)
      NO_SHIFT:  begin r_b = {i_b[14:0],i_b[15:0]};     r_num = 4'h0;  o_b = w_b_right; end
      LE_SHIFT:  begin r_b = {i_b[15:0],15'b0};         r_num = 4'h1;  o_b = w_b_left;  end
      RI_SHIFT:  begin r_b = {15'b0,i_b[15:0]};         r_num = 4'h1;  o_b = w_b_right; end
      AR_SHIFT:  begin r_b = {{15{i_b[15]}},i_b[15:0]}; r_num = 4'h1;  o_b = w_b_right; end
      LE_ROTATE: begin r_b = {i_b[15:0],i_b[15:1]};     r_num = 4'h1;  o_b = w_b_left;  end
      RI_ROTATE: begin r_b = {i_b[14:0],i_b[15:0]};     r_num = 4'h1;  o_b = w_b_right; end
      BR_ROTATE: begin r_b = {i_b[14:0],i_b[15:0]};     r_num = i_num; o_b = w_b_right; end
      BL_ROTATE: begin r_b = {i_b[15:0],i_b[15:1]};     r_num = i_num; o_b = w_b_left;  end
      default:   begin r_b = {i_b[14:0],i_b[15:0]};     r_num = 4'h0;  o_b = w_b_right; end
   endcase
end

genvar i;
generate
   for (i=0;i<BW;i=i+1) begin : br_gen_right
      mux_unit inst_mux_unit_right (r_b[i+BW-1:i], r_num, w_b_right[i]);
   end
endgenerate

generate
   for (i=30;i>BW-2;i=i-1) begin : br_gen_left
      mux_unit inst_mux_unit_left (r_b[i:i-(BW-1)], (BW-1)-r_num, w_b_left[i-(BW-1)]);
   end
endgenerate
endmodule

Credits

Won_Hyunho

Won_Hyunho

2 projects • 2 followers

Comments