![]() |
|
|
|
#1 |
|
Hello there!
I'm not a pro in vhdl, just another student who has problems getting things working like the teachers want to. We need to design a simple risc cpu, without pipelining and all the fancy stuff, and actually I got everything working quite nice so far, except for one quite important thing: Assume all operations take either 2 or 3 cycles (logic ones 2, load/store 3). Within the first cycle, the program counter is increased (through the ALU - no seperate adder for the pc). Naturally I need to fetch the opcode of the next instruction within the last cycle... and here comes my problem: The register that holds the opcode is written upon the rising edge of the clock, while i need this new opcode right in the same cycle (the first cycle (pc = pc+1) is the same for most operations, but not all, e.g. JMPs). Now the rising edge of the clock writes the driver for the opcode register, and my main control process has a Christoph M. Wintersteiger |
|
|
|
|
#2 |
|
Posts: n/a
|
grr don't you hate it when you hit the wrong key at the wrong time? .... msg
continued: Now the rising edge of the clock writes the driver for the opcode register, and my main control process has a case RegOpCode is when "011010"... So, in the end this means, that the driver for RegOpCode is updated at the same (Simulation-) time as the case asks for the value, which naturally returns the old value, that RegOpCode held one cycle before. I've been tinkering with this for two days now and I couldn't think of any useful solution idea (yeah, a pipeline would work, but it's supposed to be a risc without pipeline...). I can't simply let all instructions run for another cycle, as I'm limited to those 2/3 cycles by the assignment. I can't even use RegOpCode'Drinving_value, as then the compiler complains about the signal not being driven by the process/entity asking for the driving value. And postponing the whole process kinda screwed everything up, so that probably ain't a smart idea either. Any ideas? Should I ditch the whole thing and start from scratch? Or am I just missing something that's so obvious that it can't be seen? (Btw: Using ModelSim 5.7g) Thankful for every comment, CM Wintersteiger Christoph M. Wintersteiger |
|
|
|
#3 |
|
Posts: n/a
|
Christoph M. Wintersteiger wrote:
> ... and here comes my problem: The > register that holds the opcode is written upon the rising edge of the clock, > while i need this new opcode right in the same cycle ... If you model the opcode-register as a latch, it would be transparent. If you don't like latches (or it is impossible to use them), model a signal "opcode_next", that is pure combinational logic and holds the value of the next incoming opcode. (-> It will be hazarderous, so take care of this.) Now sample opcode_next into the opcode-register and use this signal also for some different calculations. opcode_next --------opcode register | |----other stuff Again: It will have glitches! Therefore you have to sample the "other stuff" later, when it is stable. Iff opcode_next arrives quite early, and the "other stuff" can be computed fast too, the "other stuff" can be sampled with the same edge, like the opcode register samples the data. Ralf Ralf Hildebrandt |
|
|
|
#4 |
|
Posts: n/a
|
Yeah, I had the idea of "pipelining" the opcodes too, but it doesn't work, as I don't know when the next opcode is a Load-Immediate (in case of a loadi, the next byte in memory is not an opcode, but an immediate value). RegOpCode would then be overwritten with the immediate value. I could live with that, but then I don't get the immediate value anymore, because if I had to read it from RegOpCode, I'd only get the first 5 bits, because the operand values are stored in seperate registers, which can't be accessed from this entity. Also a JMP would make the "pre-cached" value in RegOpCode invalid which wouldn't be a problem either, if I wouldn't have to introduce another cycle for the JMP, so I can pre-cache again... And JMP may only take two cycles, they say. I didn't quite understand what you meant with reusing the opcode_next for some other calculations; Just to save on the number of signals? I'm not concerned with that... heh Thanks, CM Wintersteiger "Ralf Hildebrandt" <Ralf-> schrieb im Newsbeitrag news:... > Christoph M. Wintersteiger wrote: > > > > ... and here comes my problem: The > > register that holds the opcode is written upon the rising edge of the clock, > > while i need this new opcode right in the same cycle ... > > If you model the opcode-register as a latch, it would be transparent. > > If you don't like latches (or it is impossible to use them), model a > signal "opcode_next", that is pure combinational logic and holds the > value of the next incoming opcode. (-> It will be hazarderous, so take > care of this.) > > Now sample opcode_next into the opcode-register and use this signal also > for some different calculations. > > opcode_next --------opcode register > | > |----other stuff > > > Again: It will have glitches! Therefore you have to sample the "other > stuff" later, when it is stable. > > Iff opcode_next arrives quite early, and the "other stuff" can be > computed fast too, the "other stuff" can be sampled with the same edge, > like the opcode register samples the data. > > > Ralf > Christoph M. Wintersteiger |
|
|
|
#5 |
|
Posts: n/a
|
Hi!
Christoph M. Wintersteiger wrote: > the next instruction within the last cycle... and here comes my problem: The > register that holds the opcode is written upon the rising edge of the clock, > while i need this new opcode right in the same cycle (the first cycle (pc = > pc+1) is the same for most operations, but not all, e.g. JMPs). > Now the rising edge of the clock writes the driver for the opcode register, > and my main control process has a I don't know if this RISC CPU calls itself "Prol" think that there is a problem. Assuming that you are modeling without timing making the description suitable for synthesis, the simulator should behave as follows: Imagine simulation time is currently 10 ns. The opcode is at the D input of the opcode register and the rising edge of the clock comes. The assignment statement should be something like if rising_edge(iClk) then RegOpcode <= NewOpcode; end if; A new value is written into RegOpcode's driver, but because there is no delay specified, the time stamp is still 10 ns. The control path of the CPU, which is (almost) pure combinatorial logic, is of course sensitive to RegOpcode. The simulator recognizes this situation (a signal to be updated at the current simulation time and a process that is sensitive to that change) and inserts a delta delay. That is an infinitely small amount of time passing; now RegOpcode contains the new value and the dependent logic is able to react. You can watch that behaviour in ModelSim's list window, where all signal updates are shown. The current delta cycle can also be seen in the bottom status bar next to the simulation time. Regarding the tip using latches: I would strongly discurage from using them as they have nothing lost in a synchronous design and can lead to severe timing issues. Good luck, Oliver Oliver Dillinger |
|
|
|
#6 |
|
Posts: n/a
|
You absolutely got me. It's the PROL16 - you had the pleasure of implementing it, too? Thank you very much for the tip with the list window; up to now I've always closed the list window, as I had no idea what it was good for - now I know that it can be very helpful. The behaviour you described can be seen there, although it's kind of reversed. It first evaluates the process (that generates delta cycles +1, +2, +3) and then sees that RegOpCode has changed (delta cycle +10). If only I could tell the Simulator to do it the other way around - Is there a way to? My first idea was that maybe the order of the elements in the sensitivity list could help, but I'm too tired to try right now. So instead of main: process(ZuluClk, Reset, RegOpCode) is ... it would work if I said main: process(RegOpCode, ZuluClk, Reset) is ... *scratch head* I wouldn't believe that until I've seen it. Anyways, nice to see someone from around here. Btw, I'm studying Computer Science at the University in Linz - Do you have the VLSI Design course in Hagenberg too? Greetings, CM Wintersteiger On Mon, 31 May 2004 00:40:32 +0200, Oliver Dillinger <> wrote: >Hi! > >Christoph M. Wintersteiger wrote: >> the next instruction within the last cycle... and here comes my problem: The >> register that holds the opcode is written upon the rising edge of the clock, >> while i need this new opcode right in the same cycle (the first cycle (pc = >> pc+1) is the same for most operations, but not all, e.g. JMPs). >> Now the rising edge of the clock writes the driver for the opcode register, >> and my main control process has a > >I don't know if this RISC CPU calls itself "Prol" >think that there is a problem. >Assuming that you are modeling without timing making the description >suitable for synthesis, the simulator should behave as follows: >Imagine simulation time is currently 10 ns. The opcode is at the D input >of the opcode register and the rising edge of the clock comes. The >assignment statement should be something like > > if rising_edge(iClk) then > RegOpcode <= NewOpcode; > end if; > >A new value is written into RegOpcode's driver, but because there is no >delay specified, the time stamp is still 10 ns. The control path of the >CPU, which is (almost) pure combinatorial logic, is of course sensitive >to RegOpcode. The simulator recognizes this situation (a signal to be >updated at the current simulation time and a process that is sensitive >to that change) and inserts a delta delay. That is an infinitely small >amount of time passing; now RegOpcode contains the new value and the >dependent logic is able to react. >You can watch that behaviour in ModelSim's list window, where all signal >updates are shown. The current delta cycle can also be seen in the >bottom status bar next to the simulation time. >Regarding the tip using latches: I would strongly discurage from using >them as they have nothing lost in a synchronous design and can lead to >severe timing issues. > >Good luck, >Oliver Christoph M. Wintersteiger |
|
|
|
#7 |
|
Posts: n/a
|
Christoph M. Wintersteiger wrote:
> I didn't quite understand what you meant with reusing the opcode_next for > some other calculations; Just to save on the number of signals? I'm not > concerned with that... heh When you are fetching data from RAM, address is valid for some time and chipselect (cs) is it too for at least a half clock cycle. Lets have a look at a skew: ---<address>----- ------_____----- cs ^ Here you will sample the incoming data (flipflop) (into opcode register) ------<data>----- ^^^^ But the new opcode is available earlier (not hazard-free) If you have some time (the hazards vanish soon), you could use this new data signal for further calculations before it is sampled into a register. >>opcode_next --------opcode register >> | >> |----other stuff If you would use a latch for opcore register, that is activated by chipselect, you would have the same result. (latch is transparent) => Use the incoming data as soon, as they appear on the data bus. Take care, that they are hazarderous and sample the result, when shure, that all hazards are gone. Again: This solution strongly depends, if there is time (slow clock) for doing that. Ralf Ralf Hildebrandt |
|
|
|
#8 |
|
Posts: n/a
|
On Mon, 31 May 2004 09:42:54 +0200, Ralf Hildebrandt
<Ralf-> wrote: > >When you are fetching data from RAM, address is valid for some time and >chipselect (cs) is it too for at least a half clock cycle. Lets have a >look at a skew: > >---<address>----- >------_____----- cs > ^ Here you will sample the incoming data (flipflop) > (into opcode register) >------<data>----- > ^^^^ But the new opcode is available earlier (not hazard-free) > >If you have some time (the hazards vanish soon), you could use this new >data signal for further calculations before it is sampled into a register. Yeah, you're right of course, I have that data available for half a clock cycle before its sampled. I think I'll give this idea a shot lateron, however I can imagine that this solves my problem for the simulation, but would be quite a bit of a problemmaker in hardware, because the opcode changes while settings depending on the value of the opcode are being made; Well actually no - the last cycle should be almost the same for all the operations, I'll check that out. >>>opcode_next --------opcode register >>> | >>> |----other stuff > > > >If you would use a latch for opcore register, that is activated by >chipselect, you would have the same result. (latch is transparent) > > >=> Use the incoming data as soon, as they appear on the data bus. Take >care, that they are hazarderous and sample the result, when shure, that >all hazards are gone. > > >Again: This solution strongly depends, if there is time (slow clock) for >doing that. > >Ralf Christoph M. Wintersteiger |
|
|
|
#9 |
|
Posts: n/a
|
On Mon, 31 May 2004 01:10:16 +0200, Christoph M. Wintersteiger
<> wrote: >So instead of >main: process(ZuluClk, Reset, RegOpCode) is ... >it would work if I said >main: process(RegOpCode, ZuluClk, Reset) is ... > I just tried it, and it doesn't make a difference. It doesn't even matter if I include RegOpCode in the sensitivity list at all - It's always assigned last. I wish I could set priorities or something. Christoph M. Wintersteiger |
|
|
|
#10 |
|
Posts: n/a
|
Yeah, the PROL rocks tha house hrhr. I'm doing Hardware/Software Systems
Engineering in Hagenberg and we coded it in 5th semester. Christoph M. Wintersteiger wrote: > On Mon, 31 May 2004 01:10:16 +0200, Christoph M. Wintersteiger > <> wrote: > > >>So instead of >>main: process(ZuluClk, Reset, RegOpCode) is ... >>it would work if I said >>main: process(RegOpCode, ZuluClk, Reset) is ... Do you do everything in only one process? Or is this the implementation of the control path. If yes, why isn't it sensitive to the counter for the current cycle? It is also a good practise to separate sequential and combinatorial logic into 2 processes. > > I just tried it, and it doesn't make a difference. It doesn't even > matter if I include RegOpCode in the sensitivity list at all - It's > always assigned last. I wish I could set priorities or something. You can't set a priority, all processes are evaluated in random order. I think the problem is somewhere else. Maybe you could describe what the Prol does/does not. This would be helpful... Oliver Dillinger |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Microsoft Lifecam 1.0 USB 20 Camera Drivers problem | palepups | Software | 0 | 08-17-2007 12:53 PM |
| VHDL problem - Signal counter cannot be synthesized, bad synchronous description. | shipacpoloy | Software | 0 | 08-14-2007 07:26 AM |
| Dial Up Problem | smackedass | A+ Certification | 3 | 02-02-2007 11:59 PM |
| Re: Virus Problem ** Help!** | David BlandIII | A+ Certification | 1 | 03-02-2004 06:00 PM |
| Re: Serious Computer Problem | hootnholler | A+ Certification | 1 | 11-24-2003 12:18 PM |