leg.v
来自「verilog hdl编写,六段流水线CPU.程序完整」· Verilog 代码 · 共 1,311 行 · 第 1/5 页
V
1,311 行
//if it is a load and the base addr is updated, then just leave it as the last instruction.
assign f_lsm_load_base_addr = (f_lsm_inst_backup[20] && f_lsm_counter[3:0] == f_lsm_inst_backup[19:16] && f_lsm_rout) ? 1'b1 : 1'b0;
assign f_lsm_generated_inst_valid = (((f_lsm_state == 1 || f_lsm_state == 2) && f_lsm_rout && !f_lsm_load_base_addr) || (f_lsm_state == 3 && f_lsm_load_base_addr_r));
assign f_op_decoded_ldm = (i_datain[27:25] == 3'b100 && i_datain[20] == 1'b1 && !pc_reload && !pc_reload_r) ? 1'b1 : 1'b0;
assign f_op_decoded_stm = (i_datain[27:25] == 3'b100 && i_datain[20] == 1'b0 && !pc_reload && !pc_reload_r) ? 1'b1 : 1'b0;
//load store state machine;
always@(posedge clk or posedge rst)
begin
if (rst) begin
f_lsm_state <= 2'h0;
f_lsm_counter <= 4'hf;
f_lsm_rlist <= 16'h0;
f_lsm_addr_counter <= 4'h0;
f_lsm_inst_backup <= 31'h0;
end
else begin
if (f_en) begin
case(f_lsm_state)
0: begin
if (f_op_decoded_ldm && !pc_reload && !pc_reload_r) begin
f_lsm_state <= 1;
f_lsm_counter <= 4'h0;
f_lsm_inst_backup <= i_datain[31:0];
if (i_datain[24]) //increase after
f_lsm_addr_counter <= 4'h1;
else //increase before
f_lsm_addr_counter <= 4'h0;
f_lsm_rlist <= i_datain[15:0];
end
else if (f_op_decoded_stm && !pc_reload && !pc_reload_r) begin
f_lsm_state <= 2;
f_lsm_counter <= 4'hf;
f_lsm_inst_backup <= i_datain[31:0];
if (i_datain[24]) //increase after
f_lsm_addr_counter <= 4'h1;
else //increase before
f_lsm_addr_counter <= 4'h0;
f_lsm_rlist <= i_datain[15:0];
end
end
1: begin //ldm
//if the instruction before the lsm is jump and has been exec, then, the lsm should be
//invalid
if (pc_reload || pc_reload_r) begin
f_lsm_state <= 0;
f_lsm_counter <= 4'h0;
end
if (f_lsm_counter == 4'hf ) begin //return to idle
f_lsm_state <= 3;
//f_lsm_counter <= 4'h0;
end
else begin
f_lsm_counter <= f_lsm_counter + 4'h1;
f_lsm_rlist[14:0] <= f_lsm_rlist[15:1];
f_lsm_rlist[15] <= 1'b0;
//increase address
if (f_lsm_rlist[0]) begin
f_lsm_addr_counter <= f_lsm_addr_counter + 1;
end
end
end
2: begin //stm
//if the instruction before the lsm is jump and has been exec, then, the lsm should be
//invalid
if (pc_reload || pc_reload_r) begin
f_lsm_state <= 0;
f_lsm_counter <= 4'hf;
end
if (f_lsm_counter == 4'h0 ) begin //return to idle
f_lsm_state <= 3;
//f_lsm_counter <= 4'h0;
end
else begin
f_lsm_counter <= f_lsm_counter - 4'h1;
f_lsm_rlist[15:1] <= f_lsm_rlist[14:0];
f_lsm_rlist[0] <= 1'b0;
//increase address
if (f_lsm_rlist[15]) begin
f_lsm_addr_counter <= f_lsm_addr_counter + 1;
end
end
end
//last load for the
3: begin
f_lsm_state <= 0;
f_lsm_counter <= 4'h0;
//f_lsm_addr_counter <= 4'h0;
end
endcase
end
end
end
always@(posedge clk or posedge rst)
begin
if (rst) begin
f_lsm_state_d <= 2'h0;
end
else begin
if (f_en)
f_lsm_state_d <= f_lsm_state;
end
end
//------------------------------------------------------------------------------end of fetch stage
//------------------------------------------------------------------------------decode stage
assign d_en = ~d_wait;
assign d_valid = d_valid_r & (~a_br_exec) & (~w_load_r15);
wire d_foward_ena;
//register op
always@(posedge clk or posedge rst)
begin
if (rst) begin
d_inst <= 32'he1a10001; //mov r1,r1
end
else begin
if (d_en)
d_inst <= f_inst;
end
end
always@(posedge clk or posedge rst)
begin
if (rst) begin
d_valid_r <= 1'b0;
end
else begin
if (d_en)
d_valid_r <= f_valid;
end
end
always@(posedge clk or posedge rst)
begin
if (rst) begin
d_op_decoded_raddrc <= 5'b0;
end
else begin
if (d_en) begin
d_op_decoded_raddrc <= f_op_decoded_raddrc;
end
end
end
always@(posedge clk or posedge rst)
begin
if (rst) begin
d_lsm_restore_rd_valid <= 1'b0;
end
else begin
if (d_en)
d_lsm_restore_rd_valid <= f_lsm_restore_rd_valid;
end
end
always@(posedge clk or posedge rst)
begin
if (rst) begin
d_lsm_inst_count <= 4'h0;
end
else begin
if (d_en) begin
if (f_lsm_state) begin
if (f_lsm_rout) begin
d_lsm_inst_count <= d_lsm_inst_count + 4'h1;
end
end
else begin
d_lsm_inst_count <= 4'h0;
end
end
end
end
always@(posedge clk or posedge rst)
begin
if (rst) begin
r_lsm_inst_count <= 4'h0;
end
else begin
if (r_en)
r_lsm_inst_count <= d_lsm_inst_count;
end
end
always@(posedge clk or posedge rst)
begin
if (rst) begin
a_lsm_inst_count <= 4'h0;
end
else begin
if (a_en)
a_lsm_inst_count <= r_lsm_inst_count;
end
end
always@(posedge clk or posedge rst)
begin
if (rst) begin
a_lsm_inst_store_addr <= 32'h0;
end
else begin
if (a_en) begin
if (r_op_decoded_ls_u)
a_lsm_inst_store_addr[31:2] <= rf_rdatac[31:2] - a_lsm_inst_count ;
else
a_lsm_inst_store_addr[31:2] <= rf_rdatac[31:2] + a_lsm_inst_count ;
a_lsm_inst_store_addr[1:0] <= rf_rdatac[1:0];
end
end
end
//instruction decoding
assign d_op_condcode = d_inst[31:28]; //4 bit
//type: data processing decoding
assign d_op_opcode = d_inst[24:21]; //4 bit
assign d_op_s_bit = d_inst[20]; //1 bit
assign d_op_shift_amount = d_inst[11:07]; //5 bit
assign d_op_shift = d_inst[06:05]; //2 bit
assign d_op_rm = d_inst[03:00]; //4 bit
assign d_op_rs = d_inst[11:08]; //4 bit
assign d_op_rn = (d_op_deocded_mult_accm)? d_inst[15:12] : d_inst[19:16]; //4 bit
assign d_op_rd = (d_op_decoded_mul || d_op_deocded_mult_accm) ? d_inst[19:16] : d_inst[15:12]; //multiplier has a different rd //4 bit
assign d_op_immediate_ls = d_inst[11:00]; //12 bit
assign d_op_s_bit = d_inst[20];
//condition code decoding
assign d_op_cond_eqz = (d_op_condcode == 4'b0000) ? 1'b1 : 1'b0; //EQ Equal Z set
assign d_op_cond_nez = (d_op_condcode == 4'b0001) ? 1'b1 : 1'b0; //NE Not equal Z clear
assign d_op_cond_csc = (d_op_condcode == 4'b0010) ? 1'b1 : 1'b0; //CS Unsigned higher, or same C set
assign d_op_cond_ccc = (d_op_condcode == 4'b0011) ? 1'b1 : 1'b0; //CC Unsigned lower C clear
assign d_op_cond_min = (d_op_condcode == 4'b0100) ? 1'b1 : 1'b0; //MI Negative N set
assign d_op_cond_pln = (d_op_condcode == 4'b0101) ? 1'b1 : 1'b0; //PL Positive, or zero N clear
assign d_op_cond_vsv = (d_op_condcode == 4'b0110) ? 1'b1 : 1'b0; //VS Overflow V set
assign d_op_cond_vcv = (d_op_condcode == 4'b0111) ? 1'b1 : 1'b0; //VC No overflow V clear
assign d_op_cond_hic = (d_op_condcode == 4'b1000) ? 1'b1 : 1'b0; //HI Unsigned higher C set, Z clear
assign d_op_cond_lsc = (d_op_condcode == 4'b1001) ? 1'b1 : 1'b0; //LS Unsigned lower, or same C clear, Z set
assign d_op_cond_gen = (d_op_condcode == 4'b1010) ? 1'b1 : 1'b0; //GE Greater, or equal N=V (N and V set or N and V clear)
assign d_op_cond_ltn = (d_op_condcode == 4'b1011) ? 1'b1 : 1'b0; //LT Less than N<>V (N set and V clear) or (N clear and V set)
assign d_op_cond_gtz = (d_op_condcode == 4'b1100) ? 1'b1 : 1'b0; //GT Greater than Z clear, N=V (N and V set or N and V clear)
assign d_op_cond_lez = (d_op_condcode == 4'b1101) ? 1'b1 : 1'b0; //LE Less than, or equal Z set or N<>V (N set and V clear) or (N clear and V set)
assign d_op_cond_al = (d_op_condcode == 4'b1110) ? 1'b1 : 1'b0; //AL Always Flag ignored always run
assign d_op_cond_nv = (d_op_condcode == 4'b1111) ? 1'b1 : 1'b0; //NV-NEVER never run
//operation decoding
assign d_op_decoded_and = (d_op_opcode == 4'b0000) ? 1'b1 : 1'b0; //logic and |rd = rn & shifter_operand
assign d_op_decoded_eor = (d_op_opcode == 4'b0001) ? 1'b1 : 1'b0; //logical exclusive or |rd = rn ^ shifter_operand (exclusive)
assign d_op_decoded_sub = (d_op_opcode == 4'b0010) ? 1'b1 : 1'b0; //substract |rd = rn - shifter_operand
assign d_op_decoded_rsb = (d_op_opcode == 4'b0011) ? 1'b1 : 1'b0; //reverse substract |rd = shifter_operand - rn
assign d_op_decoded_add = (d_op_opcode == 4'b0100) ? 1'b1 : 1'b0; //add |rd = rn + shifter_operand
assign d_op_decoded_adc = (d_op_opcode == 4'b0101) ? 1'b1 : 1'b0; //add with carry |rd = rn + shifter_operand + carry_flag
assign d_op_decoded_sbc = (d_op_opcode == 4'b0110) ? 1'b1 : 1'b0; //substract with carry |rd = rn - shifter_operand - (not)carry_flag
assign d_op_decoded_rsc = (d_op_opcode == 4'b0111) ? 1'b1 : 1'b0; //reverse substract with carry |rd = shifter_operand - rn - (not)carry_flag
assign d_op_decoded_tst = (d_op_opcode == 4'b1000) ? 1'b1 : 1'b0; //test |upgrade flags after rn & shifter_oprand
assign d_op_decoded_teq = (d_op_opcode == 4'b1001) ? 1'b1 : 1'b0; //test equivalence |upgrade flags after rn | shifter_oprand
assign d_op_decoded_cmp = (d_op_opcode == 4'b1010) ? 1'b1 : 1'b0; //compare |upgrade flags after rn - shifter_oprand
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?