24行Verilog写了个电脑:-)

 1 module cpu(input reset, clk, input[0:55] rom);
 2 reg[7:0] i; // instruction
 3 reg[4:0] rf[2], pc; // register file and program counter
 4 always @(reset, clk) begin
 5     $monitor("%b %b %b", i, rf[0], rf[1]);
 6     pc = reset ? 0 : pc; i = rom >> (48 - (pc << 3));
 7     case (i[7:6])
 8     'b00: begin rf[i[5]] = i[4:0]; pc++; end
 9     'b01: begin rf[i[5]] += i[4:0]; pc++; end
10     'b10: pc += ((rf[0][4] | rf[1][4])) ? i[4:0] : 1;
11     'b11: begin if (!i[4:0]) $finish(); pc += i[4:0]; end
12     endcase
13 end
14 endmodule
15 module suanpan;
16 reg    reset, clk;
17 reg[0:55]    rom;
18 initial begin
19 rom = 'b00000001001000100100000101111111100000101101110111000000;
20 reset = 1; #1 reset = 0;
21 for(clk = 0; clk <= 1; clk++) #1;
22 end
23 cpu cpu(reset, clk, rom);
24 endmodule

好像没啥好办法换endian. SystemVerilog里还可以static int...,iverilog目前还不支持。36行版:

module cpu(input[31:0] clk, input[55:0] rom);
reg[7:0]  inst;    // instruction
reg[1:0]  op;      // op code
reg       ri;      // register index
reg[4:0]  immd;    // immediate number
reg[4:0]  rf[2];   // register file
wire      s;       // add caused <0?
reg[4:0]  pc;      // program counter
always @(clk) begin
    $monitor("%b %b %b %b", inst, rf[0], rf[1], s);
    pc = clk ? pc : 0;
    inst = rom >> (48 - pc * 8);
    op = inst[7:6]; ri = inst[5]; immd = inst[4:0];
    if (op == 'b00) begin rf[ri] = immd; pc++; end
    else if (op == 'b01) begin rf[ri] += immd; pc++; end
    else if (op == 'b10) pc += s ? immd : 1;
    else if (op == 'b11) begin
        if (!immd) $finish();
        pc += immd;
    end
end
assign s = (rf[0][4] | rf[1][4]);
endmodule
// How to pass array structure between two verilog modules?
// https://stackoverflow.com/questions/16369698/how-to-pass-array-structure-between-two-verilog-modules
// This is not possible in Verilog. (See sec. 12.3.3, Syntax 12-4 of the Verilog 2005 standard document, IEEE Std. 1364-2005.)
module suanpan;
reg[55:0]    rom[1];
integer    clk;
initial begin
$readmemb("rom.txt", rom);
$display("rom.txt: %b", rom[0]);
for(clk = 0; clk < 100; clk++) #1;
end
cpu cpu(clk, rom[0]);
endmodule

assign s不对,运气好没出错,op等assign就不对了: 用错assign的一个例子@博客园

俺会写加法器, 因为俺会写触发器, 俺就是不写。:-) Icarus的iverilog.exe生成的a.out,Windows 10下可以"执行": a.out回车,弹出用哪个应用打开对话框,选择其它应用,vvp.exe,以后直接a.out就可以了。Windows学Linux,也支持shebang了。#! /c/Source/iverilog-install/bin/vvp 找不到弹对话框。

Building an 8-Bit CPU on an FPGA - Austin Morlan

posted @ 2021-12-25 00:59  Fun_with_Words  阅读(66)  评论(0编辑  收藏  举报









 张牌。