首先画出我心中的电路.该电路实现简单的从数据总线载入数据到系统总线,寄存器与寄存器之间的交换数据,加法,减法和乘法5个功能的16位处理器.Windows的画图工具太难使了,所以,整个电路是使用同一个时钟.因为是很简单的,所以最大组合逻辑电路的时延和最小的时钟周期也没有去计算,时序仿真时都是用很长的一个时钟周期.整个电路的寄存器与总线之间的连接是用三态门控制的的.贴出来,以后回顾一下.
然后再用Verilog表述出心中的电路.
- //0->load,1Cycle
- //1->move,1Cycle
- //2->add,3Cycle
- //3->dec,3Cycle
- //4->mul,3Cycle
- module sprocess(clk, func ,data , w, cycle, bus, R0, R1, R2, R3);
- parameter cycle_bit_wide = 2;
- parameter dec_cycle_bit_wide = 1 << cycle_bit_wide;
- parameter ctl_bit_wide = 3;
- parameter dec_ctl_bit_wide = 1 << ctl_bit_wide;
- parameter regx_bit_wide = 2;
- parameter dec_regx_bit_wide = 1 << regx_bit_wide;
- parameter regy_bit_wide = 2;
- parameter dec_regy_bit_wide = 1 << regy_bit_wide;
- parameter reg_bit_wide = 16;
- parameter reg_count = 4;
- input clk, w;
- input [(ctl_bit_wide + regx_bit_wide + regy_bit_wide)-1:0]func;
- input [reg_bit_wide-1:0]data;
- wire stop, func_set;
- output wire [cycle_bit_wide-1:0]cycle;
- wire [ctl_bit_wide-1:0]func_ctl;
- wire [regx_bit_wide-1:0]func_regx;
- wire [regy_bit_wide-1:0]func_regy;
- wire [dec_cycle_bit_wide-1:0]dec_cycle;
- wire [dec_ctl_bit_wide-1:0]dec_ctl;
- wire [dec_regx_bit_wide-1:0]dec_regx;
- wire [dec_regy_bit_wide-1:0]dec_regy;
- reg [reg_count-1:0]regx_in_en, regx_out_en, regy_in_en, regy_out_en;
- output wire [reg_bit_wide-1:0]bus;
- wire [reg_bit_wide-1:0]See_Reg[reg_count];
- reg [reg_bit_wide-1:0]add_dec_res;
- wire [reg_bit_wide-1:0]summand_out, ad_results_out, multiplicand_out, mul_res, mul_res_mask_bit, mul_results_out;
- wire ad_results_out_en, mul_results_out_en;
- output wire [reg_bit_wide-1:0]R0, R1, R2 ,R3;
- integer i;
- genvar j, k;
-
- //Timing Counts
- assign stop = (dec_cycle[0] && !w) || (dec_cycle[1] && (dec_ctl[0] || dec_ctl[1])) || (dec_cycle[3] && (dec_ctl[2] || dec_ctl[3] || dec_ctl[4]));
- counter count(clk, stop, cycle);
- defparam count.n = cycle_bit_wide;
- //Get Hot Only Num Of Timing Counts
- decoder decoder_cycle(cycle, dec_cycle);
- defparam decoder_cycle.enc_bit_wide = cycle_bit_wide;
-
- assign func_set = w & dec_cycle[0];
- register ctl_reg(clk, func, func_set, {func_ctl,func_regx,func_regy});
- defparam ctl_reg.reg_bit_wide = ctl_bit_wide + regx_bit_wide + regy_bit_wide;
- //Get Hot Only Num Of Func Ctl
- decoder decoder_ctl(func_ctl, dec_ctl);
- defparam decoder_ctl.enc_bit_wide = ctl_bit_wide;
- //Get Hot Only Num Of Func Regx
- decoder decoder_regx(func_regx, dec_regx);
- defparam decoder_regx.enc_bit_wide = regx_bit_wide;
- //Get Hot Only Num Of Func Regx
- decoder decoder_regy(func_regy, dec_regy);
- defparam decoder_regy.enc_bit_wide = regy_bit_wide;
-
- always@(regx_in_en, regx_out_en, regy_in_en, regy_out_en, dec_cycle, dec_ctl, dec_regx, dec_regy)
- begin
- regx_in_en = 0;
- regx_out_en = 0;
- regy_in_en = 0;
- regy_out_en = 0;
- for(i=0;i<reg_count;i=i+1)
- begin
- regx_in_en[i] = (dec_cycle[1] && (dec_ctl[0] || dec_ctl[1]) && dec_regx[i]) || (dec_cycle[3] && (dec_ctl[2] || dec_ctl[3] || dec_ctl[4]) && dec_regx[i]);
- regx_out_en[i] = (dec_cycle[1] && dec_regx[i] && (dec_ctl[2] || dec_ctl[3] || dec_ctl[4]));
- regy_out_en[i] = (dec_cycle[1] && dec_ctl[1] && dec_regy[i]) || (dec_cycle[2] && (dec_ctl[2] || dec_ctl[3] || dec_ctl[4]) && dec_regy[i]);
- end
- end
-
- assign bus = (dec_cycle[1] && dec_ctl[0])?data:'bz;
- generate
- for(j=0;j<reg_count;j=j+1)
- begin:regs
- register nor_reg(clk, bus, (regx_in_en[j] | regy_in_en[j]), See_Reg[j]);
- defparam nor_reg.reg_bit_wide = reg_bit_wide;
- end
- for(k=0;k<reg_count;k=k+1)
- begin:set_bus
- assign bus = (regx_out_en[k] | regy_out_en[k])?See_Reg[k]:'bz;
- end
- endgenerate
- //To make the output visible
- assign R0 = See_Reg[0];
- assign R1 = See_Reg[1];
- assign R2 = See_Reg[2];
- assign R3 = See_Reg[3];
-
- //Add/Dec Process
- register summand(clk, bus, (dec_cycle[1] && (dec_ctl[2] || dec_ctl[3])), summand_out);
- defparam summand.reg_bit_wide = reg_bit_wide;
- always@(add_dec_res, summand_out, bus, dec_ctl)
- begin
- if(dec_ctl[2])
- begin
- add_dec_res = summand_out + bus;
- end else begin
- add_dec_res = summand_out - bus;
- end
- end
- register ad_results(clk, add_dec_res, 1, ad_results_out);
- defparam ad_results.reg_bit_wide = reg_bit_wide;
- assign ad_results_out_en = (dec_cycle[3] && (dec_ctl[2] || dec_ctl[3]));
- assign bus = ad_results_out_en?ad_results_out:'bz;
-
- //Mul Process
- register multiplicand(clk, bus, (dec_cycle[1] && dec_ctl[4]), multiplicand_out);
- defparam multiplicand.reg_bit_wide = reg_bit_wide;
- multiplier mul(multiplicand_out, bus, {mul_res_mask_bit, mul_res});
- defparam mul.n = reg_bit_wide;
- register mul_results(clk, mul_res, 1, mul_results_out);
- defparam mul_results.reg_bit_wide = reg_bit_wide;
- assign mul_results_out_en = (dec_cycle[3] && dec_ctl[4]);
- assign bus = mul_results_out_en?mul_results_out:'bz;
- endmodule
- module decoder(in_const, out_hoc);
- parameter enc_bit_wide = 32;
- parameter dec_bit_wide = 1 << enc_bit_wide;
- input [enc_bit_wide-1:0]in_const;
- output reg [dec_bit_wide-1:0]out_hoc;
- integer i;
-
- always@(in_const, out_hoc)
- begin
- out_hoc = 0;
- for(i=0;i<dec_bit_wide;i=i+1)
- begin
- if(in_const == i)
- begin
- out_hoc[i] = 1'b1;
- end
- end
- end
- endmodule
- module register(clk, in_val, in_en, out_val);
- parameter reg_bit_wide = 32;
- input clk, in_en;
- input [reg_bit_wide-1:0]in_val;
- output reg [reg_bit_wide-1:0]out_val;
-
- always@(posedge clk)
- begin
- if(in_en)
- begin
- out_val <= in_val;
- end
- end
- endmodule
- module counter(clk, en, c);
- parameter n = 32;
- input clk;
- input en;
- output reg [n-1:0]c;
-
- always@(posedge clk)
- begin
- if(en)
- c <= 0;
- else
- c <= c + 1;
- end
- endmodule
- module multiplier(x, y, out);
- parameter n = 16;
- input [n-1:0]x, y;
- output [n*2-1:0]out;
- genvar i, j, k, l;
- wire [n:0]tmp_sun[n-1], tmp_out[n-1];
- wire [n:0]tmp_x;
-
- assign tmp_x = {1'b0,x};
- assign out[0] = tmp_x[0] & y[0];
- generate
- assign tmp_out[0][0] = 1'b0;
- for(i=0;i<n;i=i+1)
- begin:add_bt
- top_m tm (tmp_x[i+1], y[0], tmp_x[i], y[1], tmp_out[0][i], tmp_sun[0][i], tmp_out[0][i+1]);
- end
- assign out[1] = tmp_sun[0][0];
- assign tmp_sun[0][n] = tmp_out[0][n];
-
- for(j=2;j<n;j=j+1)
- begin:ftf
- for(k=0;k<n;k=k+1)
- begin:add_bb
- btm_m bm (tmp_sun[j-2][k+1], tmp_x[k], y[j], tmp_out[j-1][k], tmp_sun[j-1][k], tmp_out[j-1][k+1]);
- end
- assign out[j] = tmp_sun[j-1][0];
- assign tmp_sun[j-1][n] = tmp_out[j-1][n];
- end
-
- for(l=n;l<n*2;l=l+1)
- begin:add_o
- assign out[l] = tmp_sun[n-2][l-n+1];
- end
- endgenerate
- endmodule
- module top_m(m0, q0, m1, q1, cin, sun, cout);
- input m0, m1, q0, q1;
- input cin;
- output sun, cout;
- wire x, y;
-
- assign x = m0 & q0;
- assign y = m1 & q1;
- full_add fa (x, y, cin, sun, cout);
- endmodule
- module btm_m(sunin, m, q, cin, sun, cout);
- input sunin, m, q, cin;
- output sun, cout;
- wire y;
-
- assign y = m & q;
- full_add fa (sunin, y, cin, sun, cout);
- endmodule
- module full_add(x, y, cin, sun, cout);
- input x, y, cin;
- output reg sun, cout;
- always@(x, y, cin)
- begin
- sun <= x^y^cin;
- cout <= x&y | x&cin | y&cin;
- end
- endmodule
最后给出,该电路的时序仿真,功能测试依次为:数据载入->寄存器交换数据->加法->乘法.
小结:
编写电路时,首先要在脑海构建好自己想要实现的电路,清楚电路每一个细节的实现.例如组合电路和时序电路的每一个时钟周期的配合,组合电路模块最大时钟时延,触发器的最短建立时间与保持时间,开关是使用三态门还是多路器,是使用计数器加译码器还是直接使用计数器等.然后再用Verilog或VHDL把心中的电路描述出来.需要牢记一点,一定要清楚自己的代码会被编译器综合出什么样的电路而写代码,如果连自己都不清楚代码综合成什么样的,那编译器就更不知道了.
阅读(2676) | 评论(0) | 转发(0) |