OpenCores
URL https://opencores.org/ocsvn/brainfuckcpu/brainfuckcpu/trunk

Subversion Repositories brainfuckcpu

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /brainfuckcpu/trunk/rtl
    from Rev 4 to Rev 6
    Reverse comparison

Rev 4 → Rev 6

/brainfuck_cpu.v
0,0 → 1,338
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Aleksander Kaminski
//
// Create Date: 01:23:37 07/08/2014
// Design Name: Braindfuck CPU
// Module Name: brainfuck_cpu
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 000 = <
// 001 = >
// 010 = +
// 011 = -
// 100 = ,
// 101 = .
// 110 = [
// 111 = ]
//////////////////////////////////////////////////////////////////////////////////
module brainfuck_cpu #(parameter DATA_ADDR_WIDTH = 8, ROM_ADDR_WIDTH = 12, STACK_DEPTH = 4)
(
input clk,
input rst,
input [7:0] data_i,
output [7:0] data_o,
input [2:0] rom_i,
output [DATA_ADDR_WIDTH-1:0] data_addr_o,
output [ROM_ADDR_WIDTH-1:0] rom_addr_o,
output reg rd,
output reg wr,
output reg mreq,
output reg ioreq,
input ready
);
// FSM states
 
localparam RAM_CLEAR = 3'b001,
RUN = 3'b010,
UPDATE_DATA = 3'b100,
INSTANT_ZERO_EXEPTION_RECOVERY = 3'b101,
JUMP_RECOVERY = 3'b110;
 
// Declarations
reg [2:0] ir;
reg [7:0] data_reg;
reg [ROM_ADDR_WIDTH-1:0] pc;
reg [DATA_ADDR_WIDTH-1:0] pointer;
reg [clogb2(STACK_DEPTH)-1:0] sp;
reg [ROM_ADDR_WIDTH-1:0] stack [0:STACK_DEPTH-1];
reg [2:0] fsm_state;
reg [2:0] fsm_next;
reg ir_load;
reg data_reg_load;
reg data_reg_inc;
reg data_reg_dec;
reg stack_load;
reg sp_inc;
reg sp_dec;
reg pc_inc;
reg pc_load;
reg pointer_inc;
reg pointer_dec;
integer i;
// Instruction fetching
always @(posedge clk, posedge rst) begin
if(rst)
ir <= 0;
else if(ir_load)
ir <= rom_i;
end
// Current data register
 
always @(posedge clk, posedge rst) begin
if(rst)
data_reg <= 0;
else begin
if(data_reg_inc)
data_reg <= data_reg + 1;
else if(data_reg_dec)
data_reg <= data_reg - 1;
else if(data_reg_load)
data_reg <= data_i;
end
end
assign data_o = data_reg;
// Stack
 
always @(posedge clk) begin
for( i=0 ; i<STACK_DEPTH ; i=i+1 )
stack[i] <= stack[i];
if(stack_load)
stack[sp] <= pc;
end
// Stack pointer
 
always @(posedge clk, posedge rst) begin
if(rst)
sp <= 0;
else if(sp_inc)
sp <= sp + 1'b1;
else if(sp_dec)
sp <= sp - 1'b1;
end
// Program counter
 
always @(posedge clk, posedge rst) begin
if(rst)
pc <= 0;
else if(pc_inc)
pc <= pc + 1;
else if(pc_load)
pc <= stack[sp-1];
end
assign rom_addr_o = pc;
// Pointer
 
always @(posedge clk, posedge rst) begin
if(rst)
pointer <= 0;
else if(pointer_inc)
pointer <= pointer + 1;
else if(pointer_dec)
pointer <= pointer - 1;
end
assign data_addr_o = pointer;
// FSM
 
always @(posedge clk, posedge rst) begin
if(rst)
fsm_state <= RAM_CLEAR;
else
fsm_state <= fsm_next;
end
always @(*) begin
ir_load <= 1'b0;
data_reg_load <= 1'b0;
data_reg_inc <= 1'b0;
data_reg_dec <= 1'b0;
stack_load <= 1'b0;
sp_inc <= 1'b0;
sp_dec <= 1'b0;
pc_inc <= 1'b0;
pc_load <= 1'b0;
pointer_inc <= 1'b0;
pointer_dec <= 1'b0;
wr <= 1'b0;
rd <= 1'b0;
mreq <= 1'b0;
ioreq <= 1'b0;
case(fsm_state)
RAM_CLEAR: begin
wr <= 1'b1;
mreq <= 1'b1;
fsm_next <= RAM_CLEAR;
if(ready) begin
pointer_inc <= 1'b1;
if(&pointer) begin
ir_load <= 1'b1;
pc_inc <= 1'b1;
fsm_next <= RUN;
end
end
end
RUN: begin
case(ir)
3'b000: begin //<
wr <= 1'b1;
mreq <= 1'b1;
if(ready) begin
pointer_dec <= 1'b1;
ir_load <= 1'b1;
pc_inc <= 1'b1;
fsm_next <= UPDATE_DATA;
end
else
fsm_next <= RUN;
end
3'b001: begin //>
wr <= 1'b1;
mreq <= 1'b1;
if(ready) begin
pointer_inc <= 1'b1;
ir_load <= 1'b1;
pc_inc <= 1'b1;
fsm_next <= UPDATE_DATA;
end
else
fsm_next <= RUN;
end
3'b010: begin //+
ir_load <= 1'b1;
pc_inc <= 1'b1;
data_reg_inc <= 1'b1;
fsm_next <= RUN;
end
3'b011: begin //-
ir_load <= 1'b1;
pc_inc <= 1'b1;
data_reg_dec <= 1'b1;
fsm_next <= RUN;
end
3'b100: begin //,
rd <= 1'b1;
ioreq <= 1'b1;
fsm_next <= RUN;
if(ready) begin
data_reg_load <= 1'b1;
ir_load <= 1'b1;
pc_inc <= 1'b1;
end
end
 
3'b101: begin //.
wr <= 1'b1;
ioreq <= 1'b1;
fsm_next <= RUN;
if(ready) begin
ir_load <= 1'b1;
pc_inc <= 1'b1;
end
end
3'b110: begin //[
ir_load <= 1'b1;
pc_inc <= 1'b1;
if(data_reg == 7'b0)
fsm_next <= INSTANT_ZERO_EXEPTION_RECOVERY;
else begin
sp_inc <= 1'b1;
stack_load <= 1'b1;
fsm_next <= RUN;
end
end
3'b111: begin //]
if(~(data_reg == 7'b0)) begin
pc_load <= 1'b1;
fsm_next <= JUMP_RECOVERY;
end
else begin
ir_load <= 1'b1;
pc_inc <= 1'b1;
sp_dec <= 1'b1;
fsm_next <= RUN;
end
end
endcase
end
UPDATE_DATA: begin
rd <= 1'b1;
mreq <= 1'b1;
if(ready) begin
data_reg_load <= 1'b1;
fsm_next <= RUN;
end
else
fsm_next <= UPDATE_DATA;
end
INSTANT_ZERO_EXEPTION_RECOVERY: begin
ir_load <= 1'b1;
pc_inc <= 1'b1;
if(ir == 3'b111)
fsm_next <= RUN;
else
fsm_next <= INSTANT_ZERO_EXEPTION_RECOVERY;
end
JUMP_RECOVERY: begin
ir_load <= 1'b1;
pc_inc <= 1'b1;
fsm_next <= RUN;
end
default: fsm_next <= RAM_CLEAR;
endcase
end
 
// Function clogb2
function integer clogb2;
input [31:0] value;
integer i;
begin
clogb2 = 0;
for(i = 0; 2**i < value; i = i + 1)
clogb2 = i + 1;
end
endfunction
 
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.