cpu32

verilog 32bit cpu experiment
git clone http://frotz.net/git/cpu32.git
Log | Files | Refs

cpu32.v (5226B)


      1 // CPU32 Non-pipelined Core
      2 //
      3 // Copyright 2012, Brian Swetland.  Use at your own risk.
      4 
      5 `timescale 1ns/1ns
      6 
      7 module cpu32 (
      8 	input clk,
      9 	input reset,
     10 	output [31:0] i_addr,
     11 	input [31:0] i_data,
     12 	output [31:0] d_addr,
     13 	output [31:0] d_data_w,
     14 	input [31:0] d_data_r,
     15 	output d_data_we
     16 	);
     17 
     18 reg sync_reset;
     19 
     20 always @(posedge clk)
     21 	if (reset)
     22 		sync_reset <= 1'b1;
     23 	else
     24 		sync_reset <= 1'b0;
     25 
     26 reg [31:0] pc, ir;
     27 
     28 wire [31:0] next_pc, pc_plus_4, next_pc0;
     29 
     30 wire [3:0] opcode, opfunc, opsela, opselb, opseld;
     31 wire [15:0] opimm16;
     32 
     33 wire [31:0] adata, bdata, wdata, result;
     34 
     35 assign opcode = ir[31:28];
     36 assign opfunc = ir[27:24];
     37 assign opsela = ir[23:20];
     38 assign opselb = ir[19:16];
     39 assign opseld = ir[15:12];
     40 assign opimm16 = ir[15:0];
     41 
     42 wire [31:0] opimm16s;
     43 assign opimm16s[31:0] = { {16{opimm16[15]}} , opimm16[15:0] };
     44 
     45 wire ctl_alu_pc;
     46 wire ctl_alu_imm;
     47 wire ctl_regs_we;
     48 wire ctl_ram_we;
     49 wire ctl_alu_altdest;
     50 wire ctl_wdata_ram;
     51 wire ctl_branch_ind;
     52 wire ctl_branch_taken;
     53 
     54 control control(
     55 	.opcode(opcode),
     56 	.opfunc(opfunc),
     57 	.ctl_adata_zero(ctl_adata_zero),
     58 	.hazard(hazard_rrw),
     59 
     60 	.ctl_alu_pc(ctl_alu_pc),
     61 	.ctl_alu_imm(ctl_alu_imm),
     62 	.ctl_regs_we(ctl_regs_we),
     63 	.ctl_ram_we(ctl_ram_we),
     64 	.ctl_alu_altdest(ctl_alu_altdest),
     65 	.ctl_wdata_ram(ctl_wdata_ram),
     66 
     67 	.ctl_branch_ind(ctl_branch_ind),
     68 	.ctl_branch_taken(ctl_branch_taken)
     69 	);
     70 
     71 wire ctl_adata_zero;
     72 assign ctl_adata_zero = (adata == 32'h0);
     73 
     74 assign i_addr = next_pc;
     75 
     76 always @(posedge clk)
     77 	if (sync_reset) begin
     78 		ir <= 32'hEEEE7777;
     79 		pc <= 32'h00000000;
     80 	end else begin
     81 		if (!hazard_rrw)
     82 			ir <= i_data;
     83 		pc <= next_pc;
     84 	end
     85 
     86 /* these arrive from writeback */
     87 wire [31:0] regs_wdata;
     88 wire [3:0] regs_wsel;
     89 wire regs_we;
     90 
     91 regfile REGS (
     92 	.reset(reset),
     93 	.clk(clk),
     94 	.we(regs_we),
     95 	.wsel(regs_wsel), .wdata(regs_wdata),
     96 	.asel(opsela), .adata(adata),
     97 	.bsel(opselb), .bdata(bdata)
     98 	);
     99 
    100 // attempt to identify hazards
    101 wire hazard1, hazard2, hazard_rrw;
    102 assign hazard1 = (((regs_wsel == opsela) | (regs_wsel == opselb)) & regs_we) & (regs_wsel != 4'b1111);
    103 assign hazard2 = (((mem_wsel == opsela) | (mem_wsel == opselb)) & mem_we) & (mem_wsel != 4'b1111);
    104 assign hazard_rrw = hazard1 | hazard2;
    105 
    106 assign pc_plus_4 = hazard_rrw ? pc : (pc + 32'h4);
    107 
    108 wire [31:0] branch_to;
    109 mux2 #(32) mux_branch_to(
    110 	.sel(ctl_branch_ind),
    111 	.in0(pc + { opimm16s[29:0], 2'b00 } ),
    112 	.in1(bdata),
    113 	.out(branch_to)
    114 	);
    115 
    116 mux2 #(32) mux_pc_source(
    117 	.sel(ctl_branch_taken),
    118 	.in0(pc_plus_4),
    119 	.in1(branch_to),
    120 	.out(next_pc0)
    121 	);
    122 
    123 mux2 #(32) mux_next_pc(
    124 	.sel(sync_reset),
    125 	.in0(next_pc0),
    126 	.in1(32'h0),
    127 	.out(next_pc)
    128 	);
    129 
    130 wire [31:0] ainput;
    131 wire [31:0] binput;
    132 
    133 mux2 #(32) mux_alu_left(
    134 	.sel(ctl_alu_pc),
    135 	.in0(adata),
    136 	.in1(pc_plus_4),
    137 	.out(ainput)
    138 	);
    139 
    140 mux2 #(32) mux_alu_right(
    141 	.sel(ctl_alu_imm),
    142 	.in0(bdata),
    143 	.in1(opimm16s),
    144 	.out(binput)
    145 	);
    146 
    147 wire [3:0] ctl_wsel;
    148 
    149 mux2 #(4) alu_wsel_mux(
    150 	.sel(ctl_alu_altdest),
    151 	.in0(opseld),
    152 	.in1(opselb),
    153 	.out(ctl_wsel)
    154 	);
    155 
    156 alu alu(
    157 	.opcode(opfunc),
    158 	.left(ainput),
    159 	.right(binput),
    160 	.out(result)
    161 	);
    162 
    163 wire [31:0] mem_data;
    164 wire [3:0] mem_wsel;
    165 wire mem_we;
    166 
    167 memory mem(
    168 	.clk(clk),
    169 	.reset(reset),
    170 
    171 	.in_alu_data(result),
    172 	.in_reg_data(bdata),
    173 
    174 	.in_mem_we(ctl_ram_we),
    175 	.in_regs_we(ctl_regs_we),
    176 	.in_regs_wsel(ctl_wsel),
    177 	.in_wdata_ram(ctl_wdata_ram),
    178 
    179 	.out_data(mem_data),
    180 	.out_wsel(mem_wsel),
    181 	.out_we(mem_we),
    182 
    183 	.d_addr(d_addr),
    184 	.d_data_r(d_data_r),
    185 	.d_data_w(d_data_w),
    186 	.d_data_we(d_data_we)
    187 	);
    188 
    189 writeback wb(
    190 	.clk(clk),
    191 	.reset(reset),
    192 
    193 	.in_data(mem_data),
    194 	.in_wsel(mem_wsel),
    195 	.in_we(mem_we),
    196 
    197 	.out_we(regs_we),
    198 	.out_wsel(regs_wsel),
    199 	.out_data(regs_wdata)
    200 	);
    201 
    202 endmodule
    203 
    204 
    205 module memory(
    206 	input clk,
    207 	input reset,
    208 
    209 	/* interface to sync sram */
    210 	output [31:0] d_addr,
    211 	input  [31:0] d_data_r,
    212 	output [31:0] d_data_w,
    213 	output d_data_we,
    214 
    215 	/* interface to processor core */
    216 	input [31:0] in_alu_data,
    217 	input [31:0] in_reg_data,
    218 
    219 	input in_mem_we,
    220 	input in_regs_we,
    221 	input [3:0] in_regs_wsel,
    222 	input in_wdata_ram,
    223 
    224 	output [31:0] out_data,
    225 	output [3:0] out_wsel,
    226 	output out_we
    227 	);
    228 
    229 	reg [31:0] alu_data;
    230 	reg [31:0] reg_data;
    231 	reg mem_we;
    232 	reg regs_we;
    233 	reg [3:0] regs_wsel;
    234 	reg wdata_ram;
    235 
    236 	always @(posedge clk) begin
    237 		if (reset) begin
    238 			alu_data <= 32'b0;
    239 			reg_data <= 32'b0;
    240 			mem_we <= 1'b0;
    241 			regs_we <= 1'b0;
    242 			regs_wsel <= 4'b0;
    243 			wdata_ram <= 1'b0;
    244 		end else begin
    245 			alu_data <= in_alu_data;
    246 			reg_data <= in_reg_data;
    247 			mem_we <= in_mem_we;
    248 			regs_we <= in_regs_we;
    249 			regs_wsel <= in_regs_wsel;
    250 			wdata_ram <= in_wdata_ram;
    251 		end
    252 	end
    253 
    254 	assign d_addr = in_alu_data; 
    255 	assign d_data_w = in_reg_data;
    256 	assign d_data_we = in_mem_we;
    257 
    258 	mux2 #(32) mux_data(
    259 		.sel(wdata_ram),
    260 		.in0(alu_data),
    261 		.in1(d_data_r),
    262 		.out(out_data)
    263 		);
    264 
    265 	assign out_wsel = regs_wsel;
    266 	assign out_we = regs_we;
    267 endmodule
    268 
    269 module writeback(
    270 	input clk,
    271 	input reset,
    272 
    273 	input [31:0] in_data,
    274 	input [3:0] in_wsel,
    275 	input in_we,
    276 
    277 	output out_we,
    278 	output [3:0] out_wsel,
    279 	output [31:0] out_data
    280 	);
    281 
    282 	reg [31:0] data;
    283 	reg [3:0] wsel;
    284 	reg we;
    285 
    286 	always @(posedge clk) begin
    287 		if (reset) begin
    288 			data <= 32'b0;
    289 			wsel <= 4'b0;
    290 			we <= 1'b0;
    291 		end else begin
    292 			data <= in_data;
    293 			wsel <= in_wsel;
    294 			we <= in_we;
    295 		end
    296 	end
    297 
    298 	assign out_we = we;
    299 	assign out_wsel = wsel;
    300 	assign out_data = data;
    301 endmodule
    302 
    303 	
    304