m0_53430223
2021-11-22 18:16
采纳率: 50%
浏览 21

简易cpu如何解决Verilog中的数据冒险

问题遇到的现象和发生背景

img

在编写简易cpu时寄存器内的数据多次跳跃,当计算A+1或A-1时结果为0;

运行结果及报错内容

img


```bash
module cpu(
    input clock,
    input reset,
    input [7:0]zhiling,
    output reg[7:0] led_id,
    output reg[6:0] out_led,
    output reg signed[7:0]r,
    output reg signed[7:0]r1,
    output reg signed[7:0]r2,
    output wire signed[7:0]r11,
    output wire signed[7:0]r12,
     output wire signed[7:0]r33,
     output wire signed[7:0]r44,
     output wire signed[7:0]r55,
     output wire signed[7:0]r66,
    output ZF1, //0标志位, 运算结果为0(全零)则置1, 否则置0 
           OF1, //溢出标志位 
           CF1, //进借位标志位,  
           SF1, //符号标志位,与F的最高位相同  
           PF1//奇偶标志位,F有奇数个1,则PF=1,否则为0  
    );
   /* reg signed[7:0]r1;
    reg signed[7:0]r2;
    wire signed[7:0]r11;
    wire signed[7:0]r12;*/
    reg [7:0] mymem [3:0]; // 定义32个8位存储器(mymem[i]表示第i个存储器)
    always@* begin
    if(reset==1'b1)
     begin
    mymem[0]=8'b00000000;
    mymem[1]=8'b00000000;
    mymem[2]=8'b00000000;
    mymem[3]=8'b00000000;
     end
     end
    function [7:0]RAM;
    input reset;
input we; // 低电平表示读数据,高电平表示写数据 用开关SW1表示 
input rd;
input [1:0] addr_we;
input [1:0] addr_rd;
input [7:0] data_in; // 用开关SW7-SW14表示输入的8位二进制数据 
begin
    if(reset==1'b0)
    begin
    if(we==1'b1&&rd==1'b0)
      begin
         mymem[addr_we]=data_in;
       RAM=mymem[addr_we];
      end
    else if(we==1'b0&&rd==1'b1)
       RAM=mymem[2'b10]; 
 end
 end
 endfunction
    wire s0,s1,s2,s3,s4,s5,add_en,add1_en,sub_en,sub1_en,and_en,or_en,xor_en,slt_en;
    wire [3:0]opcode;wire[1:0]addr_1;wire[1:0]addr_2;
    wire signed [3:0]a;wire[3:0]b; 
    control c(reset,zhiling[7:4],s0,s1,s2,s3,s4,s5,add_en,add1_en,sub_en,sub1_en,and_en,or_en,xor_en,slt_en);
    always@(*) 
    begin                
    if(s0==1&&s3==0&&s4==0)            
     mymem[zhiling[5:4]]=RAM (reset,s0,s1,zhiling[5:4],2'b10,{{4{zhiling[3]}},zhiling[3:0]});  
      if(s3==1'b1)
    begin r1={{4{r11[3]}},r11[3:0]};
    mymem[2'b10]=RAM (reset,1'b1,1'b0,2'b10,2'b10,r1); end
    if(s4==1'b1)
    begin r2=r12;
    mymem[2'b10]=RAM (reset,1'b1,1'b0,2'b10,2'b10,r2); 
     end 
    if(s1==1) r=mymem[2'b10];
       end        
    // assign r13=mymem[zhiling[5:4]];             
    id i(reset,s2,zhiling,opcode,addr_1,addr_2);
    assign r33=mymem[addr_1];  
    assign r44=mymem[addr_2];  
    assign r55=mymem[0];
    assign r66=mymem[1];
    alu alu1(mymem[addr_1][3:0],mymem[addr_2][3:0],reset,s3,add_en,add1_en,sub_en,sub1_en,and_en,or_en,xor_en,slt_en,r11,ZF1,OF1,CF1,SF1,PF1); 
    MULT_4 m(mymem[addr_1],mymem[addr_2],reset,s4,r12);
    /*always@(posedge clock)   
    begin  r=mymem[2'b10];
    end*/
    parameter CLK_COUNT = 249999;//时钟计数上限
reg [31:0] count;//计数
reg [1:0] id;//id0~3对应左到右四个数码管
wire flag;  //flag标记补码是否表示负数
assign flag=r[7];

//8位2进制,十进制至多3位
reg [7:0] n1;    //百位
reg [7:0] n2;    //十位
reg [7:0] n3;    //个位
reg [7:0] abs;  
always @(*)
    case(flag) //求正数的个十百位
    1'b0:
        begin
           n1 = r / 100 % 10;
           n2 = r/ 10 % 10;
           n3 = r % 10;
        end
    1'b1:
        begin
           abs=(~r)+1;  //求负数的个十百位
           n1 = abs / 100 % 10;        
           n2 = abs / 10 % 10;        
           n3 = abs % 10;
        end
    endcase
    
always @ (posedge clock)//时钟上升沿
begin //根据时钟信号控制切换显示的数码管
    if (count == CLK_COUNT)
    begin
        count <= 0;
       id = (id + 1);//切换
    end
    else
        count <= count+1;
    end
   
   
   //选择灯,显示数字
always @ (id)
begin        
    if (id == 0) 
            begin           
                led_id <= 8'b1111_0111;//最左端灯亮
                if(r[7]==1)
                out_led<=7'b1111110;//负号
                else out_led<=7'b1111111;//不显示
            end
    else if (id == 1)//其余三个管显示逻辑相同
    begin
        led_id <= 8'b1111_1011;
        begin
            case(n1)
                4'b0000: out_led = 7'b0000001;    //0
                4'b0001: out_led = 7'b1001111;    //1
                4'b0010: out_led = 7'b0010010;    //2
                4'b0011: out_led = 7'b0000110;    //3
                4'b0100: out_led = 7'b1001100;    //4
                4'b0101: out_led = 7'b0100100;    //5
                4'b0110: out_led = 7'b0100000;    //6
                4'b0111: out_led = 7'b0001111;    //7
                4'b1000: out_led = 7'b0000000;    //8
                4'b1001: out_led = 7'b0000100;    //9
            endcase
        end 
    end
    else if (id == 2)
    begin
        led_id <= 8'b1111_1101;
        begin
            case(n2)
                4'b0000: out_led = 7'b0000001;    //0
                4'b0001: out_led = 7'b1001111;    //1
                4'b0010: out_led = 7'b0010010;    //2
                4'b0011: out_led = 7'b0000110;    //3
                4'b0100: out_led = 7'b1001100;    //4
                4'b0101: out_led = 7'b0100100;    //5
                4'b0110: out_led = 7'b0100000;    //6
                4'b0111: out_led = 7'b0001111;    //7
                4'b1000: out_led = 7'b0000000;    //8
                4'b1001: out_led = 7'b0000100;    //9
            endcase
        end
    end
    else if (id == 3)
    begin
        led_id <= 8'b1111_1110;
    begin
        case(n3)
            4'b0000: out_led = 7'b0000001;    //0
            4'b0001: out_led = 7'b1001111;    //1
            4'b0010: out_led = 7'b0010010;    //2
            4'b0011: out_led = 7'b0000110;    //3
            4'b0100: out_led = 7'b1001100;    //4
            4'b0101: out_led = 7'b0100100;    //5
            4'b0110: out_led = 7'b0100000;    //6
            4'b0111: out_led = 7'b0001111;    //7
            4'b1000: out_led = 7'b0000000;    //8
            4'b1001: out_led = 7'b0000100;    //9
        endcase
    end
    end 
end
endmodule

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

2条回答 默认 最新

  • 有问必答小助手 2021-11-24 10:02
    最佳回答

    你好,我是有问必答小助手,非常抱歉,本次您提出的有问必答问题,技术专家团超时未为您做出解答


    本次提问扣除的有问必答次数,已经为您补发到账户,我们后续会持续优化,扩大我们的服务范围,为您带来更好地服务。

    评论
    解决 无用
    打赏 举报
查看更多回答(1条)

相关推荐 更多相似问题