首页 > 解决方案 > 出乎意料的波形出来了,设计CPU

问题描述

在此处输入图像描述

我正在尝试设计 CPU 和 SRAM 之间的读写周期。初始内存值为 mem(0) = 000f,mem(1) = 000e。我想按 5 个周期进行设计 周期 1:分配 addr = 0 周期 2:从 SRAM 读取值,mem(0) -> IR 周期 3:分配 addr = 1 周期 4:在 SRAM 中写入值,IR -> mem(1)周期 5:从 SRAM 读取值,mem(1) -> DR

        module sram(addr,clk,din,dout,we); //sram.v

        parameter addr_width = 12, word_depth = 4096, word_width = 16;

        input clk,we;
        input [addr_width-1:0] addr; 
        input [word_width-1:0] din; 
        output [word_width-1:0] dout; 

        reg [word_width-1:0]mem[0:word_depth-1]; 
        reg [word_width-1:0]dout;

        always @ (posedge clk) begin
            if(!we)
                mem[addr] <= din[word_width-1:0]; 
            end
        always @ (posedge clk) begin
            if(we)
                dout[word_width-1:0] <= mem[addr];
            end

        endmodule


        module cpu(clk,reset,select); //cpu.v

        input clk,reset;
        input [2:0]select;

        reg[15:0] ir,dr,ac;
        reg[11:0] ar,pc;

        reg [11:0]addr;
        reg[15:0] din;
        reg we;
        wire[15:0] dout;

        sram sram(addr,clk,din,dout,we);

        always @ (posedge clk or negedge reset) begin
            if(!reset) begin
                ar <= 12'b0;  ir <= 16'b0;  pc <= 12'b0;  dr <= 16'b0;  ac <= 16'b0;
            end

            if(select==3'b001)  //cycle1, address assign
                 addr <= 12'b0; 
            if(select==3'b010) //cycle2, read
                 we <= 1;ir[15:0] <= dout[15:0]; 
            if(select==3'b011) //cycle1, address assign
                 addr <= 12'b1;    
            if(select==3'b100) //cycle4, write
                 we <= 0; din[15:0] <= ir[15:0]; 
            if(select==3'b101) //cycle5, read
                 we <= 1; dr[15:0] <= dout[15:0];
            end

        endmodule

        module tb_cpu(); //tb_cpu.v
        parameter addr_width = 12, word_depth = 4096, word_width = 16;

        reg clk,reset;
        reg [2:0] select;
        integer sram_pointer;
        integer reg_pointer;

        cpu cpu(clk,reset,select);

        always #5 clk = ~clk;

        initial begin
            clk = 0; reset = 1;

            $readmemb("sram.dat", tb_cpu.cpu.sram.mem);

            sram_pointer = $fopen("sram_aftercycle.dat");
            reg_pointer = $fopen("reg.dat");
            #1 reset = 0;
            #1 reset = 1;
            #3 select = 3'b001; //cycle 1
            #20 select = 3'b010; //cycle 2
            #20 select = 3'b011; //cycle 3
            #20 select = 3'b100; //cycle 4
            #20 select = 3'b101; //cycle 5

            #10
            $fdisplay(reg_pointer, "AR = %b", tb_cpu.cpu.ar);
            $fdisplay(reg_pointer, "IR = %b", tb_cpu.cpu.ir);
            $fdisplay(reg_pointer, "PC = %b", tb_cpu.cpu.pc);
            $fdisplay(reg_pointer, "DR = %b", tb_cpu.cpu.dr);
            $fdisplay(reg_pointer, "AC = %b", tb_cpu.cpu.ac);

            $fdisplay(sram_pointer, "mem[0000 0000 0000] = %b",tb_cpu.cpu.sram.mem[0]);
            $fdisplay(sram_pointer, "mem[0000 0000 0001] = %b",tb_cpu.cpu.sram.mem[1]);
            $fdisplay(sram_pointer, "mem[0000 0000 0010] = %b",tb_cpu.cpu.sram.mem[2]);
            $fdisplay(sram_pointer, "mem[0000 0000 0011] = %b",tb_cpu.cpu.sram.mem[3]);

             $fclose(sram_pointer);
             $fclose(reg_pointer);

             #5 $finish;
         end

        endmodule

这是我的模拟。选择值可以表示循环数。正如我所料,当周期 2 开始时,mem(0) 值 000f 分配给dout,所以dout 变为000f,IR 应该在下一个上升沿得到这个值,但是 DR 值意外地与 IR 同时变化。问题出在哪里?

标签: verilogxilinx

解决方案


在 always 块的底部,您有一个if没有begin/ end

if(select==3'b101) //cycle5, read
   we <= 1; dr[15:0] <= dout[15:0];

这意味着分配 todr将始终发生;只有we <= 1被条件覆盖。


推荐阅读